SIBO 'C' Software Development Kit 


OLIB REFERENCE 


Version 2.30 


March 1, 1999 


(C) Copyright Psion PLC 1990-98 


All rights reserved. This manual and the programs referred to herein are copyrighted works of Psion PLC, 
London, England. Reproduction in whole or in part, including utilization in machines capable of 
reproduction or retrieval, without express written permission of Psion PLC, is prohibited. Reverse 
engineering is also prohibited. 


The information in this document is subject to change without notice. 


Psion and the Psion logo are registered trademarks, and Psion, Psion MC, Psion HC, Psion Series 3, Psion 
Series 3a and Psion Workabout are trademarks of Psion PLC. 


TopSpeed is a registered trademark of Clarion Software Corporation. Intel 8086 and 80286 are registered 
trademarks of Intel Corporation. IBM, IBM XT and IBM AT are registered trademarks of International 
Business Machines Corp. Microsoft and MS-DOS are registered trademarks of Microsoft Corporation. 
Apple and Macintosh are registered trademarks of Apple Computer Inc. VAX and VMS are registered 
trademarks of Digital Equipment Corporation. Brief is a registered trademark of Underware Inc. Psion 
PLC acknowledges that some other names referred to are registered trademarks. 


CONTENTS 


1 Introduction.............sccsccsssscrssersserscsresesceeeeseceseesssesseseseesseesseesseesseessesssessceescesscesscssscesseseseesonees 1-1 
sits: OE IB Classesic. 7 scp beet eSegl ocd sdee hand tego eck snug bantstes’ cet ocep sant tact eetouepbantstgecboreeitabetes 1-2 

Notation se: cscccteaseasteessdsatcaesiseb cesedsas ceceuahtecsvica secuvdcnbecuvdene cevyachncebavicardcsbidandees dendenvccnneebvess 1-2 

INAINIES 20, aac set cacao Ae Seva achvtact dee velit anh Bet daa vautontutuctdentuetomtativedeevaicteatetect ows 1-2 

Method function prototypes ...........cccccccccesssceeceseeceeeeeneeeceeeaeeeceeeeeceseaeeeceenaeeeeeeneeeeeeeas 1-2 

PRE G:SyMDol is, osc fg l Secs vant te soges Wipeest bt codes sah eiet es odebseep sant hls cesteck Pui eedabeeramae 1-3 

LON 8: Parameters so.t5 esse eestesistestediadestedia des tetiadesbtaads vemr hehe tiphaaaeliohatiehee 1-3 

Class (las rarniss ses.3 02 c.cs(toeesthet sanvaes cas thet aceesiid ca thbeterevated oes thetoms iiatows eieheaevstnon aes 1-3 

Class hierarchy,.2:s.2i0iinsGiien tien cei Ca aktoiee vein cei ia eres 1-3 
StructtiredJRrror RECOVELY ..: ccs ccnccregescooepsssicongessbeaupsseteens oduteavpnsbcadsueds bed psdetadessdebspevecesesey 1-4 

Use of the p_leave mechanism. ..........e ec eeseesseccsseeeesseecsseecseeecesseecsseecsneeseseeeesaeeesaeers 1-4 

Pane NUMBers..e6s ese Stee nt cag eteal Cok etecahectathaabss sche abhadhubk dah aes sO dana hamaseel aa lau etuae es 1-5 

2 THE ROOT: Classsiccsscccsctssasessasencooseseesessusacsasssocesosssbsccoessasosoevedscsoasossesouvesssconsadcesasbadescussewassessess 2-1 
Class: Geta ti oni yse si5ecenk6 soaps scaceseeibecastevens dekes sncace coungaaaeuaneceewergcenesencconeneseceaseacesnese 2-1 

PLOperty *iisessis Asap eicovie basdiiedeh cent hardier daheh badisodartid Avvdis datas Ausiiaieeniat aeons 2-1 

ROOT Cth ods acpi: soss7s eas obs shes eat adh coe acens eupiti ed Soa ciien cea dicod dua Ties Seat of ota Ueeh sea te obs dha leee Saas 2-2 

Destroy: the:tistan ce 3, s3iissaccsiesaniaiiseeteaesscatlaisacelescaacanesiecealesnah atiseutaatidertaniaseusectegsed 2-2 

3 The TIME Cass............scssssssssssssesscsssessscssscsssesssessscsssessscsssesssesssesssessscsssesssesssesssesssessscsssessoess 3-1 
PEECUTSOIS ieeet ciyecan cts fovea snneedanetedeuagannpacensvedotngouteccetetedeinboutsceetevedataceussceenetedadscusenesseens 3-2 

Class definition .siccccccacecciecoean aeeisatecoedsas (devise te cavices cdavicencdevicae CUevicadieevacae cde vaceadenseces ees 3-2 

PLOPOrey, oi oe: Sock in ut Ses Gloss teenken ses abet ccuvaurt Soe alot oan tienes alsvestitratens Giateasther den bivbeaetece ote 3-3 

TIME Methods csssisscccssccanccsestanccsecvarcesersas ceseswancenvavancens seancenvacaucebscetndesvacseceasccdedeeecanccaaceae 3-3 

DOL TIIME ay. forced fi leaec sc oeasaadu cede edhe odesets locos etic cceas et ce vheniata sd ovaabeuverinvedserionedtesdcavedvaeevedade 3-3 

SONSE (UME sevice scsicdestedeiese deeds cedsgiuadcdaeduadedevisabecondsetedevisatcdesdendedeydenbedevccnacdbvvigandevvics 3-4 

Add S@CONDS >. 22 ce. ioete cs caeh eee tite dh va sd ae Ate oe dad eee NOs e, aesla es naledonsdacstonnaebeds destiale 3-4 

Add: days wicdetsii vid i eiiaedl ea ie ee vee ee a RE 3-5 

Ad TOMES ios datedeeete Selec cate leas take Leia cata dena de Soceva dake ctaotes ebivdcavadupede (ecieecetolanedehedey catates 3-5 

Ad YEatSs cs.250teoyrive gees tegieee a dayhiduseshees haber oe vQighe ben eae aben ahaa 3-5 
SENSETOPMALH seoess cen LEM eet cceses he Neaeeteen oc ROM acerbec de Gack steetenk a Manian ses Guien ent deck 3-6 

Set fOrMat. c:.seececdiveeecsgaceacceaa cease vesscccgeseanceaescet cegetsarceavscar ces duancenvicae cons cetneesvecde cdaveuts 3-6 

Get system date and time information............ eee eeseeesseeceseeeesseeesseecsseecsseecsseeesseeeesaes 3-7 

4 The SGBUF Segmented Buffer Class ................ccsssccsssssscsscssccsscsccssscscscsssssessssssesssssssesssecsees 4-1 
PHECUESOLS§. « cceci05 feo2 268 Foss Bec Ais Bek cous Fa bee BeBe ok Bek PEP Me cov Hove tele derevd Feuadeit Pe desovt Paadeeete 4-1 

Class etitittion, ic vceseceiters hc catesi toads eteatealesertoateccameauaeasaatecerteateqersaatageusaateoersaateases 4-2 

BIOPerty sc. ssh s5 chk Secs Soetes ohccah cies dies co chansne desnugcochaneucausbuacconenehodwuguns cagneceneuevieeacaaenseoeg’ 4-2 

SGBUEF methods sec) cicecscestiecsdessciesovsthdessesuseastvst idasduantdasoveticunesctdeassusaddaescesseasseenbinscreacias 4-2 

DG StL OY: 205 ies cues cas teibe sel stuns cedeeves dul scunscuvtcuve iva stukeseTsavbes inh steve suv tcuvadas stees eUbsvessebaceve cede aus 4-2 

WMI ALISES sxts.terssictec sts Aes tee tec cen ts Agectec certs ee cstds aces tens tes tactsa Bde tds tac sa Ande tiniaeie 42 

Sense data by position ...........cececccceessscecessceeeeesnceeeeseeeeceesneeesseneeeeeseeeeeeseaeeeeeeneeeeeeeas 4-3 


INSEL tet t taht thea dnctata coi decd td host ected hh tated bale Booed Shin 4-3 


OLIB REFERENCE 


ii 


Delete iaics cevstensPevsarhsrets tues fevsanasdesstensdeyscedes cadens suv stevs duacdeve deasdevareadevsivensveasevedvosusscvesd 4-3 
EXtract: fcsssssccscadseieessasisss adeeseseasshaceandeasooatesiecsotdaaseastetiasevagsaseestegeaes sbdsaseeete shassendaessens 4-4 
COMPLESS eoiss ci iesssceeoeisacacoeds cvdgoss Seeauockccgdensd ce gesochdesdeschcashgustegvouubes goavete dedgauh Seesseebsgetaus 4-4 
Count Characters ...t..i50.5..sses Aaidasts asses dasstest asses idsseh stewsees Hetsssdavdiee savieseaaedisaceteds 4-4 
Sense previous Characters: ,2..5sc2sisects<k.aseeedhoeccts Savasubediaes aches aciwssts Aysievbstiwssda sees 4-4 
Allocate:Se SM ents s:..) savcscstecttishicesvasuetcaieataneatacnsesnd slsseateauedesraaeageabascsseuessngeateaeoaaaaay 4-4 
5 Variable Array Classes.............sscccsssssscsssssscsscsseccsscscesssscsesssssssesssscssesssscscesssssesssscssssssscsesssesoes 5-1 
PRECUTSONS 45 fo fee.t cts testete genet oct beet stage aucouspnsnsedegets ceanpasneede fous ceavptutedegetutsausasutsdefesnasrevede 5-1 
Class. didetatns:.22cvscaieneavin gyi nara igh eee ely beset alae: 5-1 
NSA PE SUMAIMATY cs soctics co S62, octet set a eh ones sun svt fnbdu ony sunt cae lol ducaevSuunees ostdustnatses dates sasbeeesd 5-2 
Record pointers s:icss2avgiiteieuiviat hn ieineveaia tens Savigeinieni eave sei ab aa eates 5-2 
VAR OO Toe iisston fotetstecndn atts ited tort aca detlee atin, ck deren DN adstlts ca atte, adteawe os eat dep stay Fes 5-3 
Class definition 35.3 s.yosecg.sdeshndesteeieiiet cies bes deeipiaes dibs be dasylesb dig ded yen dain dey 5-3 
PHOPOCEY, 5b os iv Ses svct one biav oct cb eet ove ebGute ch Vouk onesie teae count caso Mute ae SaaWleavelibtess cnunt see onions vaca 5-4 
VAROOT ‘methods: :ccs2ishehel nein eri eek Bel av RL tea Behl ee avd as 5-4 
DDE STLOY :Ferssactis Sects tty erate dig eet oye catere pete corey ssstovepsteberephistesu peta te deynsstedvesSatedivadatersesdasedeveds 5-4 
Count: records .sisc.ntyegiiiie avin Slee enyhitisr eel inen aisha anes 5-4 
Append’ PECOLG: yeetes se snort Sak cal ostr tae cet GU cae aunt eet att antes Son ab eave at aM eeevtte 5-4 
Insert:a TéCOrd 3.23.8 oss se giitei eu tei ei eavesivt ates Savin inte eavai iain mania 5-4 
Delete a record ct ssecat on adseteyeent fp atagave pat tedover great iter ote eh paiat ie rot aaee Oates ae 5-5 
Set key for comparisons) .:05:2205,5:100.)00s3 desde ai aaeb idee ee edeyie eee Derderian 5-5 
Compare two records by POinter ...........eeseeeeseeecesseeesseecsseecesaeeesaeecsaeecseeesseeeesaeeesaeers 5-5 
Compare two records by NUMDET ...........eeceeseecesseeesneecsseecseeceseeeesaeecsaeersaeeseteeeenaeeees 5-5 
DOLE slesspsantiveyoaseentyDaeteaeeoduteens subse psdas sdesvaeh sveysdeg sav auubeveyodegsate buebeunvedebsunpreebsvtue ded oueyeds 5-6 
Find (binary chop) css. aiss cients Gopi eevee deyheitesieestighbeni et Qipkineni a audhin 5-6 
INSELEIM SEQUENCE. 385 2 sis Arte Sa Alois et ot astern ee Rho cat veld Soh ab oan ees Ghee 5-6 
DCALCH Roksan ei Hes eee seats ea vii au ai eave vca saves uaaetausaar area eeuae ares 5-6 
ROSCb is feces tails esti cep eeat stg cates ch gees Steg eane ave poeateteg slate de gaunuetyy suesace peiathae palttadegriet eégeseheveraes 5-7 
Replacea record 2:.2-scsaHecatpdned causes begtpassd eas eed paid ees ego Belgie elevates 5-7 
Deferred VAROOT methods 000.0... eee eeseceseecsseeceseceesseecsseecseecsseeeesaeecsaeecsaeecssaeeesatessaeers 5-7 
Copy: Fecord ai.ssessctivad ee aii eee al ce el a ee a a 5-7 
Get PECOrG LET StH ose, cesta slr scete capstan ty asut eteeetet slip bastedepeteductys te deetet alvh sete ined bottatoy 5-7 
Swap two: records: .:...s:.saiyictesytest eevee agieoes aiyeeibeshedeel Gishaddeaydel Gitaayh ens 5-7 
Tin 1a Sc Pot Se fe cee Sach Set Seek aan bie owe cba bet conn ete hat eos Baton tat oa catenins 5-8 
Seticapacity via eei asi savas eis mathe) Aaseaaeeesl Ai eigain Saver guc daeraielae 5-8 
COMPTESS 0. aveeaiter, ses Dever deegeset me pole lee paiutete psWiedapsenced yp slaules paietete pelttadepaaet ete grdessveveds 5-8 
Delete:sequence of records: 31.2 ce.ssec3egeystes ainda bed piaid odes bes edepdans odes belddepiasbedes euldeyebes 5-8 
Insert sequence of: TECOrdS 50.500 ee sttedk eet ee te eh ol oee eh aed ems te ot eel eteeahs 5-8 
Point tortecotds:, sighs vat tiikwhdl sai. a ae ee 5-9 
Point:to-PECOtd ata, «ssc sae set cous ante estevesc Soest bsbtedhpedeseeee bint echcevopouey bashowbeevenbeesndas hy 5-9 
WABLX oe coche es ivberee ieee ain dase abe deloeeayhi seeds shai dusoyartbebighesdesopondd phe easyaibghiphesegsvienbeleyaene ds 5-9 
Class: de tirinti Oia cicties se eect See dase eet see Lebeau fon doers ig aes ab oaes nat eee dhctenes tes 5-10 
Property eisiseiSiitete caves cash ist leaves ease eeatdis ees ae eave ees Oe asees Se 5-10 
WABEX tiie ods ise) zac coco deco tts sicedee sing oton ctetetet ete olteavecedet bee, edonaedbeathts alana eeatide, otaevep ees 5-10 
Replacé arecord 3s.t s.yerigsategned ceiesbegipassd aac es ede plait eter ede dand ieee es eels 5-10 
COpy A. TECOrd |i. ia eset Bese cae oh fetenk aed ee diet aattneal one Siedsoh eden taste tant ae steteree ats 5-10 
Get record len sthissssssvhil eed ei eh a 5-10 
SWAP tWO-TECOEGS: x25: esesctsleyssntecupete dosuyesnh ote stot odeybdetae vey etatedevsceterts edatedevbeobactpetstenteeds 5-10 
WASTR vateeste es iitens ieee civdssnegisaeliesaydies aie heiessvore Gigi avn ashes Giehileynn eran 5-11 
Class:definatiom '. esse, s. Sicetecn sens tittnast yestote teat test cantons Uist cen chitonts tet centers tes 5-12 
PLOPCLly, 2s sitar aileasese aiaileatta wai aieaiasvist aint tui as oanbae ah auieateere aie 5-12 
WAS TR: methods :sj ois: Sereda sates iececetlate patos ie de beep ate ai geest tO alate aise btes adh eat Stave ees 5-12 
Initialisé.;cci..c3 tsa ial eee aipieel Gases ant aipinel Gaebeipi ines 5-12 
Set Capacity ssi Anan ews ed ce steh Ad ett ated hut eet died kt hd Dead elk, at oe 5-13 
COMPLESS Festi iekviNi shoes ert chs a a CN ins EGR se ade hy 5-13 
Delete a sequence Of records ...........eeeeseceesseeesseecsseecsscecesaeecsaeecseecsneecesaeeesaeesseesseaes 5-13 
Insert’a sequence Of TECOrds 3.5. s..550. alps cssasiesess Seay hes beeovees Gigdes ieeovoeee igh lecoviewsigyeenees 5-13 
Gret TeCord Ler StH vs. sic2 sie Sc ces bat sak valet ets tbiee Sak alt cakes dee elds eek et seh eal oak auet Sus alt aahcies 5-13 
Point toPeCOrd ss seteieavasiintaiteinn vier an raiser dials aia leniaraiele 5-13 
Poti tstoPecord ata iss fy <dscceersces ener ed etes or dadses wi deest ea pscensst peter ee veden ste yeebeassotepeetp tates 5-14 
Copy aitécord 2..:cscisctitaniitaineh mia auienielAl a epi n aia marae 5-14 


CONTENTS 


MAGA TT 20 cc 25s tus sachs duos 2ivsins s2ube covets beiiasavis PaybBebsda savbe palate bsdeudtues fusadeustonstubeseisduvsteySeevesenndet 5-14 
Glass defiriitionss::c:ic)nistocsaacuths teense aosndaetieass eda oronlacntonasoudaken tia 5-14 
PLOPELLY’ oi esses Bases secteeeh cpdeaes Sepbanshscsbeuubocsbovsbeasbovun de ybauste cevauchoeyscouhecesuacs Seetaecbeseventheess 5-15 

VAPLAT methods = i.5:5.t.cuns cist Ae ahstenh eA inedoheohe dha sats 5-15 
Tn tal Se vice ssc. beget ossets Bue pats tessseds dave ravatvosbods Biv apabade stots deseeuieteystobs Reesvbsdevseebadvassvietuvess 5-15 
DEL CAPACIEY cesi.css sic hasondassesndceis seat aeciaigasd aeanganciasea is sestaaeneaataaaeshesasgastenuaceabassoasteasy 5-15 
COMPLESS sock echacciss ioskouhs coafecs bisibasd cdebdocicdes deckadesduutedsedusdodsoivubedesduud ocesdcbedethorsafeveusseees 5-15 
Delete sequence of Tecords a soiescssetiess sseispsaeiess Avisos aphisl vsviiaeserdiss Anoiissnarbosh aebabe 5-15 
Insert Sequencé:Of TECOLAS: 522.5505 cocks fois Sooke, SQvue Pai bcheeceh stuks eubnebsden stabs suotebusten sunbeaete Pek 5-15 
POinNt tO TECOL sesst iatscesdstaccctestacesadaiosenag anesadaiapsasagiaosntaiseeatan aouskeateeeban osendausceanea tol 5-16 
Point to record datacs icc) sscilstei seieta es Neko ad bh a ebanehi adda elon adedeecrolorshisdedecetend 5-16 

VASEG. ch. A woh isn a nkeanns uhone isl lanediilohs Moniicieiahs. 5-16 
Class: defimiti oni ss os3. sits avscsisssehs ted eshadeeseets shveratateosteds doses cdetegstedsciseevds eveevbadiasevistavess 5-17 
PLOPOLLY: eis sszssesccatacuenesadascvatastssospacaseastatadpospasasgasaazasseybasarsantadadeahegeaseniasis ovate huageshagass 5-17 

VASEG amethodss:isitii tii etlisscei ened fuselage eee ck a Se dd SE a 5-17 
Uniti alisesssco.scAseest tations: Aecsneseehisi dA secens Abnaies A aodeee setdons Anodesicasedoss Asehaabonegon Avedeaices 5-17 
SEt CAPACIEY 5 s zee eos) ees dea Saphs Beal 2uss Lea Pengesue Seve fes Paves sud Fave ienaeens dep dube Seesceys and eabn coveceyssen dt 5-17 
COMPLESSss:.ivicess shes isaceusteatethstousdaahbestestasevedaaigotetiasesedaateostesiaedeelsibeetaslasved ndsestesisy 5-17 
Delete-a Sequence Of TecOrdS iif hein haddacalsiadiacd ciedaacileie nae 5-17 
Inisert:a: Sequence: of TeCords s5..t).c:08 Asinisie pie Mas hae Mi Awe ee 5-18 
PotnittO ECOL 35 oss sesters seks eebsth oss da Ae Seis tess Saath ts awesna Aan eeig eres Gin enue Aan tae 5-18 
Point to record datass:.:isiscetasescessg id tic tapsatasices dda tspvatdaiscos dia izsateaacasdiategsaneagastiahaoess 5-18 

NAXVAR b05 5.3 osc sbutia Sha Bosdoe sh abehidctaved saubiousolevaveb navbar lodevinn abt welowe aisles 5-18 
Class definition iisoiss nctissiA sec sphasssesvtanhsvsedussdsacitse hathses vapsaboass bois AsotveedoapokeAssdvaseed 5-19 
PLOPOLLY ais sceseees neds ceebeeh Stevesesbtivs des neetsseedeve ies eevee duvatevaceus side tubeeys Seuyseis stuvsdea aceysors ede’ 5-19 

VAXVAR ‘methods: .s3seccustaviesaiagiacssetasa ventas iacendaaoeatag aoeetaerenteg assets teeslegiaeeestateosieaias 5-20 
Tin tial se’ sci sess chess ces schba sidies se sbab hasta es me obabe dud eotors shstete eeheots eoestelbgkedeeeotsreheoeetacees cet 5-20 
Compare two records by pointer .........eeeeeseeeseeceeseeeesseecsaeecsseeceseeeesaeecsaeerseeseneeeesaes 5-20 
Deleté:a:sequence Of records 520550: As csistiessida stab csiethossuendhne cavSteessues dead eebadhoveuesdbiereiadhs 5-20 
Insert: d:Sequence:OF TECOLS 5 .sescessesiiceaiisuspesnesuiteansesag eau sietentadaubensaaisteniadenpeasaanoasicees’ 5-20 
Replace records; ...5.4 sats ice eeieet ahs latee dda beet eas eed heh eed ak 5-21 
Copy a@ecord ssi sist satiee  soisiaatiest Asetesp echoed A aitere Matis Aaoteas bation Anoieasaeties Antiass 5-21 
Get récord: lem ethic: 2.528 ccsy.ccgseies pbseces covsceenset avks cas eebeaeh savas eavsedesdeh sinks restexesebstehereeiees 5-21 
Point ‘td record datas: :.cisissectsstecesad testes lassetda teenies tassatdasoastgaiarestladcasteniateudateateaisaess 5-21 

VAXEVARS 8355 cschh Selsey Sach uahl beech 2s ok eed Sa tecoubocoubved | dubeeui Seobuveds avhensh oewsabehs dekueut cevseehe gohesuh ees 5-21 
Class definition’: cic. Bat Laie Monahan Acnslad Mihsthoe Mini oie Meets 5-22 
PLOPOLLY fos cdes 30s Peis tens sc5 sched seta tens sedh caus feusdavs eth cebs eeMnteosrete Sees feiateoseets Mune eteesscsbtevaeeedet 5-22 

VAXVARS methods - see VAXVAR methods ..0.....ceeeeeeeesseeeeneeeseecseeseseecesaeeesaeeesaeers 5-22 

6 Editable Document ..............scssssssssrsssrsserssersserssessesssessesssesssesssesssesssesseeesssesessssesssessssesenseees 6-1 
DoOCuimMent: CONLENE: doses cides asia hedess debs dedecebeause cabs tevetedsdescdats Gocedeterupedeheaedeteborupsdesstiy 6-1 
Addressable character positions ............::ccessccssssessseecsseecsseeesseeeesseecsaeecseeseseeeesaeeesaeers 6-1 
USAC eee ses Sit ceetits es sath oenvalts Seu valet onus ates cee velntoaes tenses adams trstems abate utietste act ots teveortt 6-1 
PECULSOLS His cathe eves estas caveats seaval mates mat ea tare aat aseaueieeaTaasea: 6-2 
Class di aorariis ial siyadecdee fetat te vatogtiigesat te votes i peasthtevoteasigaiat uvedeuseg har etat eps tadewsp ees 6-2 

EPROOT 5:55 scscerieechbecisbesbetes Tab Soe Dati Tas eased das ewe bea aed ee zaps em epee 6-2 
Class-definition cx 6..i00t.2. mail tet ele Aue et at Alt an eat ett 6-3 
PLOPCLLY She ests avd ait eR etd Ae hd pe eed te a eats es 6-3 

BPROO DT neth Od is. 2c3) scccesut ties cstecnyesa pede busters ade betes Seeterndaded sing beetcaudede seit besten dedehedtsPexteeed 6-3 
Del CONTENE acc ceivsesbdephuee at eiph Hedin eiyhel ie sedee Qiyheh nL aee Aves besirana dain oe atest 6-3 
SCAN; DY WOT Jeter fa eheteceehas A above ct al Sb tek tina ab ecivuat at abuteeahine At ai edivtantonet 6-4 
Count Words: s.fealnavgiste eueviiia tenis velit oavai iin mane aame reins 6-4 
Sai by Paragraph oi cesses Pies ite cedeseeedeses sie evens ce dodetledh p esate edozes poe vonnede Poses yohesdetnveeadeesaee 6-4 
Count paragraphs <ts.aietudestnttadsteneied aera aay betaibha tied 6-4 
SCans DY DIOCK:sycscecee teats aed cael tet Vavcd ages adetack Gavel oath snus acbVerct athe eihtech oust sana neetesbvanstsen’ 6-4 
Append:a paragraph .:incieteicaiiensaiiie viii ae avalos avalos Aieasese ieee 6-5 
Copy whitespace indentation ............eeseeseeceeseessseecsseecsseeceseeeesaeecsaeesseeseseeeesaeessaeers 6-5 
Copy range to front of clipboard... eee eeeeeeeeneeeeseecsneecsceceseeeesaeecsaeesseeecesaeessaeers 6-5 
Copy range to back of clipboard 0.0... eee eeeeseeceseeceseeeesseessacecsscecsseecesaeeesaeessaeesseeeses 6-5 
Insert from, clipboard..:::. ss. sshstetssatees nevis sienteei cesveeissasi ote main oatauanaesiaintes 6-6 
Modify characters in a range ......... ee eesecssecssceeceseecsseecsseecesseeesseecseesseeseseeeesateesaeers 6-6 
Copy: text to: buffer... 32.538) gieeiteni pitt bhecisdeite mies gig eite hs Aaya Rae 6-6 
Set document Capacity s. ..: vs: cout segechvstas Sev, seitonk satte seehasbevbect sna bieteeeshavesteabtbeveetetesstebaus 6-6 


iii 


OLIB REFERENCE 


Deferred EPROOT methods ..............:ssccccccccesssssvvescccccecesssvcsccccceeenssevsecesceeeesssvsscessceenessees 6-6 
Tritt lise sss. ct42 toads herent ths aise en kect et istac ints es sisthc ne hsdc te iatie ek de a dtatic 25 Sour Be ioc 6-6 
Sense document len sth ss: sic. ocilends shout eelonedl shui vslereh iach Helonbserhbadd beleibecdeaks 6-6 
Sense Characters forwards. .........cccccccccccscsssseeeccccccccesssseccccsssceuseeeccccsseuecesecssseeueeseeseess 6-6 
Sense characters backwards..............ccccssssssccscccssccssssccccccsscesssscccsccssseessescsescsseeessesesees 6-6 
TM SETE CH ALACTCES 2e25.c5205.25.ctcesiaees Aces taskcees ga AGosRGaSea saad AG a REGE NA aeRTED OSE ReE Aca e Ie O 6-6 
Copy Out Characters s..5:.c5065 cestineisduadoctecghtisvedeaiess odeslosvoleubevbadesdurbedes dvaseoredbavocseboduagectoe 6-6 
Delete Character ...........cccccccccssecccceseccccueecccceseccccusecsscuseccssueeceseueecessusesessueesseeueesseeneees 6-6 
Clear the: document: 2s2085 205 ccs reoiacec tea leassrededcvedea less dledehedes daegeseDeeehe deubgeuesebedevedes Seved 6-6 
Compress: allocated storagersis.c:sccibsssccescecaoeeadausce biccacsondauseeeieaeaosundaseastgaiasonnbanieasteas 6-6 

IES EAN Mies ore ac ort es eee ee eae eta eae ct Sta, eee Se tae aoe wach. out aie Meet ce Oe cul teat ache tee ail leg 6-7 
Class definition ............cccccccccccccccsceeesseecccccscceessseecccsssseussesecesssseueeseeesecsssseeneeeesccssueees 6-7 
PLOPCRLY 3 ozs ccssceus cuvteeds tess ds hessvbtines cous eve evbsaues cessakbs peuseres sevsdee pevathossevs dues edtevesces covets 6-7 

EPBLAE methods osc22c% teestsres ices tecteetiate ates ie teeter ts ate Sela Tr te lie ee Solar teas Sole? 6-8 
DEStHOy sso scib esi ied csbccetsdubdosh Sisnceuis ietdovbasuhdivbedu Govbeduhdivsudea Seetacceivetedeadesteduaieuheloatevscdgeene 6-8 
Initialise tsk ated Se Att eta el tae Se teed aes tah teal A eed et ee tad end ks 6-8 
Sense document lem eth sos. 8.1553 2655 fev Ssens sue devs cov ssnss sues dove Sos aceus send Puvetueitebeauasedebstvbsces ss 6-8 
Sense Characters forwards. ...........cccccccccsssssssscccccccsccsssssececccssseesssecceccsssescssessseeensesseees 6-8 
Sense characters backwards.............cccccssssesecccccsccesseeccccssceesseeccessseceesseecccssseeuseeesseess 6-8 
Tnisert:chiaracters:..2332:3.cc And Ravana whilain tania Adana 6-8 
Copy out Characters i.isiecccis sass cossehas ceva chan cevachessevs cha ssvva uss sea ceussvucdavssedessevsdvecseds iueedss 6-9 
Delete: Ch aracters:45 32225. scsic a6 tes Ssnecte sia soet a Sieeste datos reasea ested aos teatearatessebaneauieeeteasearnets 6-9 
Clear the Cocument ................ssssscccccscessssvsscccccesenssevsceccceeensssvsscccccenesssvssvesseneesnceessees 6-9 
Compress: allocated stordger..ssesiscshsscAdssiesispive.desvienesuss dass svactibe vardiesseanivsssusrderensse ds 6-9 
Set document Capacity: coset seis cosh zeus devssusy sve cuvetevssusesvesduvistoussipncvhs fetsteyesntssubesebsteesee ss 6-9 
Set buffer sranularity: . .:isscs.sesiasesi lates .teslascatlesess beatae at loasoastea sce aadosoestesioceasiaadeeetats 6-9 
SOMSe Star Ol CAL sce: soi vecjic cea shes duck oe chews sanscees Goebow eho cecves dewhuwina cpanebedsdeeeiee bane oveneenee 6-9 

RSE Getter Al ad ese Lek nd A A Ste Deed btn dee ed oon ta deed be sie dee kOe kke oe 6-10 
ce) FeNoSoira 00 1 6) 0 UR re a tr So PP eS 6-10 
PLOPELtY.. fessaccssesisccahssysa cand sikteetases testes lecaehausdcasasast sabagesceusa nase duaacasdestasaseeatates toute cant aed 6-10 

EPSEG methods.............:ssccccccccessssssvscvccceeensusvccccsccesesssnsscvccsseenssescvseceseessvsssseeseeeesuvesceens 6-10 
Wniitialise teh 8 Se Atk oa ed te he as ad ae td ha eh had lahat ee Shea CA 6-10 
Sense document length ...............cseseesesesseseesoeeeenscnsvectencnessonevssesensstenseessoneesenseneneeess 6-11 
Sense Characters forwards. ...........cccccccccsssssssseccccccsscessseccecccsscessseeccsccsssescessssseeesescsees 6-11 
Sense characters backwards.............cccccsssssescccccsccessseeccccssecevseeccesssseeessesccessseueeeeesesess 6-11 
Trisert: Character ss... 50s c0035cccbei3 foca beads ooubs Fi desabecd dviads fe dsaadacliviese advanovidevie ds Adssabsstestedi hess 6-11 
Copy out Characters s.isiecscsssasg ceiseuessethaiag retadioosets cia ssvateuss Uackussvadavssedeosevsduecseds duecdedse 6-11 
Delete: Characters:45 032225. scsucae tes Ssnestas acaetiasie ceheassGoenea see satan snGastcasea sates at ataG sheeted areas 6-11 
Clear: the :dOCumentt ui secseccc loess eli zeve ces Sea ia i tiecttes La eaten nl ode yesehe Den tees ode beset edesdueooaedeee 6-11 
Compress:allocated ‘storages. csescsesiss dasdekesesghias teandadeoesedib ace scdde nsroeeedeassabsonanbsiensees 6-11 

DT, RESOURCE HINES 5.5, 6.4 scacseacaataccetetecescdesctaccdsseccinsnsevadssstecssnneseoessdetenanzescecdsdeteassctesesescunsncdotecsunenons 7-1 
PRECULSODS 2.95 <fetis tees Oe cakes AG coe va cee eS eaee ate case a Beste cae OAS cae ect cae ee 7-1 
Class. definition iss. 2222ecses Mase ee ng a ee de UE ee Es ade 7-1 
PEOPELY: sees oes 2c utcdevedon stu sactecavgeeet suurodsveveusast att oath congouusstugonch voce suatstheedsteweeseubetsyeaeeaecvets 7-2 

RS CELE: Meth OdSissi.cesc3ec3 eset es oa a ee Ve A 7-2 
DESY: c6soseet eek A A RBA BRE AA BNR A AN aS 7-2 
Initial SO isiosee iat sehi les et eh Rese ve eR ee Ee SS 7-2 
Allocate buffer and read reSOULCe ..........ccccccccccceseeeeeccccccceeessseeccccsseeessececesssseeueneeseess 7-2 
Read PeSOUT CE ai zictcaccti eee eich Recbes Basa v du pe Be eee Bi See ewe E a eae waa b sven a Oa who de aussie 7-2 

8 Binary File Management ................scccsssccsssscssscssseccsssesssssscsssscsssecsssssssssssnsscsssscsssecssssssssssosses 8-1 
PEECULSOLS Ss 2 este tiette tts Moo ter tase ncstistic eset ss it cs tsthn ast aticeurte tn aches ects he ce 8-1 
Class diastatii 2.5 issih iievneleadtheda late adult skid ei teeta ncesbe reseed 8-1 

IBE TCR etitsst dct ta atta ata acted ts am ited De ied acted esd ited eld Mise Weed ble 8-2 
Class:de tintin: 2.3 208:22 ossede doer o55 okt eve Have teco Races oPePhS coe cole Sune Debate Sec eDe luvs feNeteceen de deve Bese 8-2 
PLOPOreysssisuec sssdsacessdeuss saeasascistacesceasesaseuatatessasbesesoeshatanaosbatassasbedanaeate sasseotedwsasatasesons 8-2 

BFILE methods ............cccccceeeseccccccccceeseccccccsseceseeecccsssscueseeescsssseueueeeccesssseeeeseescesssseeueeess 8-3 
DeStr Oy. ssiss sons sestiaes de stoees svstbeni ha stass castes Aasecnasosst tanh sssthigs suet dass daetbaas ovetbess seatdess sues Sos oed 8-3 
Open Nessie eseccs heel eager Heed aeee nse Al iegsect isl aaeceast Abdel aes ethan tekst 8-3 
CLOSE files: cicdikedstesiaseedssedstaasaseancasods tad asetds Aes elas BOSSA AES 8-3 


iv 


CONTENTS 


Rea fr Or Fil 6 2s fesees fogs 2es Pes ecacdeg stevs eesdihedatedevs tea dtcecdad stuvatesstebe ealsdevstenitees fa s3H 8-3 
Set bullerSiZess:ictaticeeies tee codoncdetisasanteiehus ao iedatehtdsiaa eee is 8-3 
SENSE TECOLG 'Aatais: cisicicisisssiicchisisieseociucedeseioscbesehessdoses oeuseehessdoseasisnesssesvieselored 8-4 
REpoOsition to: Start...3.8scseiceetdeessbesde tebe ssiebeortedeviseesbiiseetedeioee bik ortedi one bits 8-4 
SEE NPE. See saute Raaesb cere th ok ovds ahs bcebsts aoe lba dwbcug ste ose Da duehcenede Seo adiee beads oe aden ead Se stereos 8-4 
CVasSsdebinitiOny sic2ccc2s2dssesstic ansscacesteaoastastiecatesteeskessatoates hoasteaseacstesaocsbenseeconessaeees 8-5 
PLOPOrey ssi scckssceiesid Sesdeuk be csdock Sesudors sfetaerhs devanedoasecuhoassdueioaveacete dueceatorsSaeuboisabovsoietaesselss 8-5 
TLVFILE methods .00.......cccceecceccccccccesssseccccscseeeessceccccssseeeesseccecssseuseseeecccsssseueeeessessssuuneness 8-6 
Open: TV le vss cessecvses Sevscadseleeced taevscepteivoees Saves sedvsed aise server ieee dsatordsucsca ste 8-6 
REpOSitiON 1O'StATE +. .sissscssssscsaseslassessteaesdeesdaasessteaasesesdaaseusdasessesdaaseveseaasovesdaasouetesasoaes 8-6 
Count records ............:sssscecccccceessvvvsvccceeeessevsscccsseeessvvsscceccueesuvesssecceeesenvssceecensessvesssees 8-6 
Wite a LECOI ...........cccccccccecssssvesccccceeensssvsesccccesensscescesccssensuesssceceeensssvescecessenesnseessees 8-6 
Set CUTENE TECOE yore co eos ss obs teess Ra deshecdetenssebsduabeadeoss dadwodsnbedeossbadeeseeteduess Wedemseeeees 8-6 
Sense current record NUMDEL ..............ccccceeeeeeeccccccceeeesecccccssseeuesseccecssseueeeeesecssseeeeeess 8-7 
Delete a record ...........::ssscscecccsssssvvvscvccceceessevssccecceeessvsescececesensucvsescecseeessssescessceneesseces 8-7 
ReplaCe:a:Tecord sss.c..stisstsesshessorevbins Anphiasceun ie Ae idessacations Ap tisss eis dnedsseasedewoaeedibe 8-7 
Read record of specific type(S) ........:ceesceescecsseecsseeceseeeeseeecsaeecsceceseesssaeeesseessaeesseeeses 8-7 
TL VIDA Avis teh itcitn .tstal dinette eRe cnc stac Rater nthe eRe Bade sa otee ha Belins Rictee Re Bede doc 8e 8-8 
CV ASS CERI tl Onis 43 icf eekideiihe ci coebadudeccacenagvetodedeusa ceus Ses Seveceass vosielodenecuadseudeetedevesiensesseee 8-8 
Property oi: Jnisi ethan Bhsi habs dashsitieiindaiida ibd hao Aan sedi Aains 8-8 
TEV DA TAs ict 8 rscinc sesh ctscinccets fash eeetic oss Daan ate wie eadeecbereee use ie danse vies emseeees 8-9 
Open and read Hess .sscssssvsssssssaseagsauasesusdsasiaasdvasesesdwabesnsovaaedwabestsdveseated vate sesdvaoesteo ees 8-9 
Save: datator Tile ssc: i025. 25 si eke cet aces Seek Such nothoc eneeeh dew tgoul sees euicneues Souk cen cecbudettvedctesieebenev eee 8-9 
Checkat changed s: 0: Jes. fattesicey ha Asthsisasiote Aatisbieue iets Astisusaoslasrdagiesinnsals Saphass 8-9 
Process a record read from a file ........c cece ccc ccccceseeeeccccccceeeeseseccccssseeeeececccssseeeneeseeeess 8-10 
Get a record to be SAVed.............sccccccccssesssvvscvccceeeesssvsesccceeensusesecesceeseeussssscssceeesnseessees 8-10 
Reset allodatasscciso cc cc28b ssi coos cectenehsdcdeceacewasvetedededencs suevetedenadeasivecseledeveceasscieretedevedenssener’ 8-10 
Deferred TLVDATA methods .0.........cccccccccccccesseeeeccccsecceessseccccssseeeeseesccsssseuuesesesesssseeneness 8-10 
Set the TLV file characteristics..............ccccsssssssscccccecesssvscsvvscccccensesssescecccesscsenssnsessees 8-10 
Set in-memory data for a record 0.0... eee eeseceseeceseeeeseeesseeecsaeeceeessseecssaeeesaeessaeessneeeees 8-10 
Sense in-memory data for a reCOrd .........eceeseeeesceeseeeseecsseecseecsseeeesaeeesaeessaeessneeeses 8-10 
SERBIMGE 7.24553, nts kvtsst ete sods eens Abe hehe aed aS ta eh hae Ok it ad ee fn tO 8-11 
Class de tim tions gees 28 sees cts 2d bees ce ae snd eee cetleeesdDctenoeeleevedd Leeheeetlgesseed cebec eS vebede 8-11 
PLOPOrey. wici.cissisessesiassondavissatesiassendavssectadasteshdsvaseetasistoesdsavendesisteandsvibeetasiateetdseeeataa tes 8-12 
SERFILE methods ...........cccccceeccecccccccccsssseccccsscceusseccccssseeussesecccsssseeevseeccecssseeeeeseceesseeees 8-13 
Reset all data.............scccccccsssssssvvscvcccecensssvcsccccceeessssescvcccseensusesescscceeesaesssvccsenensnveessees 8-13 
Set the serial file Characteristics.............ccssccccsescsccccsscsssscccscccsscessesesececsscesssessesssseesees 8-13 
Set in-memory data for a record 0... eeseeeseecsseeeeseeeeseecsaeecsneecseecesaeeesaeesseeseneeeees 8-13 
Sense in-memory data for a reCOrd .........eceeseeceseeceseeeseecsseecseeeeseecesaeeesaeesseesseeees 8-14 
DO The: CLEANUP: Class vsvsccecisccdecsasncsvecesessecsancssavcesestoccascessesssessecessssvesescsanccesessvesessaencccsessascaseeens 9-1 
PLECUESOLS .f5.c3c5sesvedeaoige reset cubes dhe yaeeon da vbes td do veds Dasuvdae videptee va devduesdgevesnbd guvdoee ddevneenesvenees 9-1 
Classdiaeram i250 28 attain oiled Mal eee al ae ea en 9-2 
Class Cetin tl Onis oeicvescoses eels ves biecde oeseudtsdas vei ose aod dea Ee 9-2 
PL OPCLUY: 4 Ben csgvsssatete daduss deaades se dedes svesacesevesodes sass sadtsde voles seuscuateassedepessveest seu vedebesepeeeteaue 9-2 
CLEANUP Meth od siscvescsesccseseceirtet aise Garb Sev eo Renee aoedes en ee eed a eS 9-3 
DOS OY. cose: eta ces teehee BO ee ae Oe este iat Ae eR hit sete OR aR 9-3 
Mmitialise:liSt:o3 sss eee ee Sh eee a es a es 9-3 
POAC sets Sect cdedetebaties sete A daebatcs camhe tedewicus eae heeds todedes oust dotonedic stabs todethetistaehadee 9-3 
ReMOVG TCE Ti sso cceecst eshte tase ase ad castes ae ae bee Cea See se Sav eae 9-3 
IDG leven teint se x Ae Bn ale A cl RM Ba RUM ah it Reh ah hin La Ble ad tot an tele 9-3 
Delete all items at current level ...............c0sssccssecccceeessvescvcccceessssessvecccssensvcvscvcesenenssens 9-4 
Bel cleanup EVEL 3. v/s rer ewacsetssvetes saa deces seus dees aude codetustuehectdevateae sbustecs dese oteepentovedeantene, 9-4 
CLEANUP convenience fUnctions.............cccccceeeeecccccscceeseececccsseuseccccssseuseseeesecssseuenseeeeess 9-4 
AGG an TtOIi hs se ttt ae clean ahaa oe can ht Sal A eh et ak 8 eh, ae Lak Jt eh, bn dak Zod Sk, nce PON 9-4 
Add an object .cc8nickinaveinnciiiraive al aa eave ee ia 9-4 
Adda: I/O. channel ie sce sisi cetctideses sdvcteeectedads dsdesevasievedesedestieusiedodesodtsaseostededasotusteescdes 9-5 
Add'an allocated -Cellisii..ce 5 ivbcsac cesta eivk cbc Savas Bev ce kbs dav bu sv ev pecs ae doves avs n bev bewe ke 9-5 
Add a:shared:allocated Cell ic. cies cccctuce ceseabetschedant ccucsvceccea tune cuvesieeccnsduveconesetectesdueeseeceee 9-5 
AGG: a DYE xs hooey Ge Sect ast aleastiaaetsu aloe desde ee eet 9-5 
REMOVE2AN AEM 06 ce acca eaelcertsoteysddgeteaecedateuevecsued ate cskeseasoeteseedstescasoteetedstesc ate svddedS 9-6 
|B Y= Fei asee2) 0 ah | 08 Cee ete eae ew A at ee ow a a Pea a te oe a 9-6 


OLIB REFERENCE 


10 The APPMAN Application Manager Cass...............sscsscssscssssssscsscssesssscscescsccscssssccsesssscsseeens 10-1 
Active Object Pri Orities ss .syssec sees secgsces steceveseactaeca stucedvedechere sted edtpodsteteguaeteote eusteevpunet#s 10-2 
Active object ‘scheduling s.::2sc.ccinsceineniiiipenide tine. ieee leona iaeaeainns 10-3 
"Phe 'a0--T ON FEtUrM: VALUE ek. 8 8 ee see lB ee ete See hined sas GO ok Bek see RR eS co Rs 10-3 
PLOCUISOFS asses sai iver eb ei Reeds eh A Beit I BU ee eee a eeieraeeNs 10-4 
CLASS: aS Tami elo cst ce ate salee eek cidade tots beat <desetes ois restedesetes ates ientevevened tanbawiaretoetescetes 10-4 
Class Cefimitin icc: cesscseceevecsendeveigens cavacnecens cdancesedandesscdaadesvadeadesucdeedeaus cosdeatadenssavceoess 10-4 
PHOPCEUY. isos sek cote acretiics dur cies cane tuet see abn t ota siuk tavauteaiv syne cee (alwtedes Watses dautetietagt Se Gute a 10-5 

APPMAN Methods o..d.cccssccseicaectesicaeceesccaaccesccaesesdenasenvecdadubudedaceaucdsaceundepasvatceseevancesseeateds 10-5 
Tint altSO%. oan seevactess darecevedvaatevscaaazedenasasrvacantevsvedss oevvedsavisetesscicedesavigcnesededsee Meet A 10-5 
Wait on I/O semaphores: ...:2:.:.505.2.cpiteditedinieed aevieibedivdah dines bespine eens detbdadeebece 10-6 
Start Scheduler 08 ote cette Aad lee tliteexlaesdeaseitidece daesd ae dbo Gee ete Aa ieee 10-6 
Stop: schedtilergssccnsict. vei igi ved iv Ri bia ee i hea are ee nee eee 10-9 
Ad ataskes.2. occ stcscereciecvesediveceteredots Gets sentecedelstedevbcstecedetarelivrinteccuedstelevicntedededssedeerds 10-9 
Load a: TeSOUrce isis ccessccdeeeeccidie vases cae shdbasaedisbesaeiaboesandesvedelieseedardeveuserdevvasrbeveusanbesvacs 10-9 
Load a resource to a DUfP EL 2.2... eeeeecceeenececeseneeeceeceeeeseneeeceenaeeecseneeeesseneeeeeesneeees® 10-10 
Generate resource file MAME ............ceceecceeeesceeeeseneeeeesceeeeneaeeeeeesaeeeeseneeeeseeneeeeesneeeees 10-10 
Display TOtter: 2. sescset states getec scees deh gadat ppevedeuseh ga sec eaup odeseee paien sep edesbee grates ovat eee eeeet ss 10-10 
Notify an-error:..si.t.cyiiecthaee teeth eee baesd (BRP a eGR ERE ER Raa a 10-11 
Clean up resources and report AN CLTOF 0... eee ee eeeceeseeeesseecseeceeeceseecesaeeesseessaeesseeeens 10-11 
Find application image file... eee eeeeeecesneeeeneeceseesneecsseeceseeeesaeecsaeesseesseeesneeeesaes 10-11 
Ensure only One COpy FUNDING .0..... eee eeeeceseeceseeceseeeesseecsaeecsaceceeeessaesesaeessaeeseeeenee 10-12 
Change active Object Priority ........ cece eececeseccesseecsneecsseecsseecesaeeesaeecsaeecseessseeeesaeessaeers 10-12 

11 The ACTIVE Class and Active Objects ..............cssccssssssssssssssccsscsecssscesssscssesssccseessssesessseees 11-1 
PLeCUTSOTSyésiscdstaticestdsasesttaiieesadataacatds ooensa aaes tea ioarsiateceatea oo tia eee ion lista atioaes 11-1 
Cass Ae tamiti omnis sss. cish 255 eesensecn ccvnctel benadha ceusenst age ieneaceva diel onetateacectaneteaunedenseceetetsinnerehed 11-2 
PLOPerty wisscicssseecne dic ocasdtetess Mapbasasete ds i Auanduad cated esdvsndasdshdeds Padvaaseedscdedi todvandestsetsiesbovs 11-2 

AGTIVE methods:.5.3 cies cute zyore ha Seeneeh teu ece da sven cidade neces dead euvtdyeeec¥a sues ceUa dyads da See teedeauetecds tuned 11-3 
Destroy the instatice .:-icsssgsisccaiieessiasdaceei caus candi icasigeaagesssaiossispeatas aoedeatseateneaonelass 11-3 
Initialise the anstanice..i2.c5<cicsii.ceccgeckccchcecssietsneees oiuhelepodeedoeseactssvenshenevadenoeseetseederectes 11-3 
Make -airequest toirutls: iscsi A sctisenstiss Aathstdnien Anriesi ann eeu einen ae 11-3 
Cancel a request to Tun vs. itscssssesscavssed stays seitcavesdsaevessanecvsssdseves seitcvesstsswessusscevseeh steusee 11-3 
Hanidlesan: errors: ic: .aisaccsatavicestaniaceenceieeasseniacantanieactasiacoutinion tasiaceutentoueted asunndansaees 11-4 
PLOCESS! ath: SVEN EG ci ccs sous chek Seve ewes Saye coed lewd ewes sand outed Sevdewws sawe coed Seed ques Sawaawes Sevbeis Souhewenleebest 11-4 

12 Idle Objects and the AIDLE Class ..............csssssscssssseccsscsccssscseecssccsesssscscesesscscesssssesssssssesess 12-1 

We OBjOCtS s.ccsecicvecseeieveian aes tiated ec anndeeucdand eve danndes uedagdest cde dea uecdaedeatliaadsauidenesatidsebvabiaspasbiees 12-1 

AIDLE), «.\ bectseeenctih ahiat eit aad see iota eee te Lo a hae ote bites 12-1 
PRECUTSOLS:ecsleecese aids eer edteese ia bev iaseceau cos ae a veeb tea e eaee cea Teev eP NN ReeA eves sR NeeTegEeNeLS 12-2 
CG laSS: dia SE aI ont fes oat echige eet ges Seat so date odes acct edad eet le beeke de peegeies cote teyedatvesntedesotereals nists 12-2 
Class Cefimition i s.cccssisesceteiesavdeveedanicseesardevecderachvucandees stand evvedapbenscdaadesuedagdeaucdeveeatedeees 12-2 
IPEOP ELEY. 6 ose ok ocs ante bet vee ck ett oaea tect seesaw tone Seve eu Cauat cake tacbnts oaliteces tevests Gaus otha teeketnaaheteess He 12-2 

AIDLE meth ods ic: ccscicah cess cevsesancdecevas devedsa nce icaa cove dcnac du ccaacueudedeces vadda suaudedacsascdaadvandervestees 12-2 
TVA SOs ose d od scites Seance vdestue cae evtenecedetats cog rebeceesdesetdeatas ecstatic cédaust seesedessMeetesscudetstecieeass st 12-2 
RUM eee eaec es bees sa 5 a Be Read os ew aa ehh Ten gat eae bs Beda bee edo dea bedeb bg bea vaee anaes 12-2 

Examples . 230i ein ia el Ae ae Ae an Aeon Ghee ates 12-3 

13 Timer Active Object Classes.............cccssscccsscssscssssssecsscssecssscssecssccseessssssessssesesssscessssscssesssees 13-1 
Class diasratn 2: 5.20585. Se Hn A SS ts SL SE eg 13-1 
PLeCUrSOIrs isis thess A aodeasovstiess Aaasbiacconteess seandian oengeeessusvdseeseasguee svandeenceasbas dvandebacessbeaboud 13-1 

"EIMER 3s 2203co 2:53 eeended segs ent cebaded Soeuscuee suescehsdexs custauvecasdunvs tush lvecehsdune covtsuneg ch fuvnedee thoes Sieneds 13-2 
Class: CetnitiOn: sceissstacdteovstes aon sade ties chasis sala ade teaacenetahecstea age elaedancasecentase tess 13-2 
PLOPOLly: 6 soaicch odes se cdeves Sa stgwesdechveuh ocbh cockscsteuus degdgostacsbevubecubausie aveumenca poauute esbaeuhoeeseerh oeevech 13-2 

TIMER methods:....02. 84s uaada end ahaa asain aontacn aaa netted: 13-2 
Tin tala Ss :2:. 5.0; tees seta degst.Ye Seosduda be wseeis Sees cebadeccseds deesdeg ade ustavaduusdusaguasseda duaduvetvecseds tueaeelsd 13-2 
Olle (relative): s<.ce35:4 scores esas iets neezessacanncssk aoakesas oa uacash tebe ae UST EI Os TES AOD 13-2 


CONTENTS 


Queue: CabSOlute) ec. 200c es s2ces ve Bees Pee Pbces Peve es Pevadvhe PeVe dees Pevbbeue Peds Bes tevsdebe Celedees Povbbeeetevedec 13-3 
ANIMATOR< j5:.cTiscsisvesnarssndaviceehaginnesadaisecanag aoecksshtaehan aoseudaieecatag apsekdasoasaenapeuadaseasteiiat 13-3 
Glass: detamiti Omics, ccsenctt Seng8s ccstetsactecen ta veanctyant esuntant ciunoactesunde ceeretgneneseiseceswengeetesteadeoeiey 13-3 
Property ui. cissi wih nhhinnes dabndnhsiinindaii dai eanhediakeie 13-4 
ANIMATOR: methods 32.0555: Abs csistiessba tive coisteoss Ds shvs eateteosechs dvs subathoseods divesvateesichadioes envy 13-4 
Initialise 
Run........ 
BUZSND Aside ion sitet cid atis bathed issphbievi A siteas seebisl vsteas erases Anodiaiaetioe Mattias 
Class definition 
Property 
BUZSND \meth Ods0eic5 ce; oi aeks Shel lace iath coehan u aed descoen Geeta cod auscees couscaeheavscceaemesnceneseacees 13-5 
Tita SO: etess fess oilsdcads ls ovts teas ceceheabectedianeeceda casa te sua cevaedues cute ddatsavnnaes cubseeec eseauns suuatiaedes 13-5 
CAM COs sos cies Seuseuittaws cave dexcenvachussevasunotigavevssevachwncepaduessdsacenasuydueveracsdusesuveduesevesdeverebeaey 13-6 
OUCUS 2 ipcccsses cher te thre tistteetie ie dke coats e oat teettnadesterestaticrat tse raatecie rete ttereetstie cates 8 13-6 
PRU pei she sot ied Soe Gaske Tou Goeh Pek aev oak oPaw Se av eow dah hehe ae dak So hgeEL Toscana bk Ge goede ab bas 13-6 
14 File Active Objects .............ccssssssccsscsscccsscsecssscssesssscscesssscseessscsesssscssessssesesssseesesesscssssssesesoess 14-1 
PLOCULSOIS ...ceztecceseyeedensebbidietiseede vanes cabin besbedencesaadeueeeddanocna ceuudendcdanosanudevds ov cdertievecevaliy 14-1 
Class: diaeramiit sis 28 athe ea aid Ma al aii hah ci el a ieee eaten ibs 14-1 
FAGTIVE aistectniiais Sevan ha tauicardiaa esavei ial iisarai ni anmaviins onan Aaa reiiney 14-1 
Class Get nat OM ors cecedecdeeeiavscedeee ee ces eiiveceucsdeuel sehvedsuaddeeceadte ecebevngeyesedse sdeneddasunsorsaods 14-2 
PLOPEI ty see cec 552 beasebes beeen aes ates beta yas aac heaved ween ng dou beebedeveaaa dens bevacdandaaa de vdvonudeviaetevubers 14-2 
PACTIVE methods's.c0 3.00.8 neste ie ati eon ie ee oe Ne ae tebe eth Oe oes 14-2 
Thi th alis@ sis; vesecssaceseiadievae cesvevascedaveas degen sau coasvty cesevenrceaevene covuecnacesvaetuessvecaacesvdeda cuiueaaaced 14-2 
Cannel de eect sreouck ccedenstadepenehcvescaukoteyogeta vet eiunedes obetares elu bedeg  ueteved eta todes sechevegedabetep cashes 14-2 
Handle: errors suc cecevs caevielbeckecesecni ves aigbetesecaandes taeba bese ddancehaadevdeee Ghavdesdedvedens ovtanoeeenaeyy 14-3 
Close. any, opentiles atx .a.tee ait titan cit ts ai tut al able A aie tt 14-3 
ESCAN fo setosstienich. tei tends eater a tales ear aieianieav aie eniaieie aime eaereliees 14-3 
Class Cetinitl OM, ois. ce.ccieccescintie ccessvsde ces suntecesssheecesans decshanteeceuantsedenadheagesaragoessardanunsodecots 14-4 
POPOL ty s.eeses3hooRades ediv dae ba san be beds vient dou beave duvaenngeeu de vedendanecdeide ony dandaaeuervaveuudevineteoubery 14-4 
FSCAN ‘methods: :. ae. cteecctee vice ache bites abst ace adedaes Woe ahi sleteds aeease satan Saelems chen Gut inns 14-5 
Directory féad +. ssncei eevee eke eee ee eve ee Bi) 14-5 
Process read: COmplett Onis, so. <cessz. ty gut eis etegeces sant tute veubeny ssapstedetes bens seeteedevepecnpsdeesnty os 14-5 
Close directory filés.:.:.cc inca ya tenia chieniini aeiies el aeytee nil anpebeaeits 14-6 
Match a found names. i. civics ces caiad ce aucd ca beeades tisk aaa ca eitaces tvs eas caveeaas Siekeencseedadua veakeae cde 14-6 
Start a:directory scais:.:.iss mass ain eaieidaiaenicattiriniatanierainat ences. 14-6 
Deferred FSCAN methods.............ccccccecesscceeesceeceeneececeeeeeeeenaeeeceenneeesseeeeeeseaeeeeeseateeeenaaees 14-7 
Scan completion y:.23.:2.y3s0s00) aviesteeil davies syed des need ylides needs 14-7 
Next: diftectory name 2.5.8. a00 vic od eat hon ee AR lee ihe eed eto 14-7 
Next file namie si. is.cccecss cess iestcdeedcas cess deaec des cedaceescedasdesceasnccnucaecensectucesvecaucesveaacuuaeaadens 14-7 
Bind: Of SUBGIFECEORY: 5.4 <5, sectenndetet sits testenssetesstegtanteveyedebotegsintedtecesodep saat ethtetehores santa 14-8 
FINODE issiecpsistenseeieiecshesedabe tel begiy sash lpi psaes Bind Tesh ydene Sivas desponb eevee begiaees epee Lay 14-8 
Class Ge tiniti oni is ch Ate ciedete nt dtenst hack oan ctectades bisects saboeaaes bes ean obetetas tick danaseatedua suntan cies 14-9 
PLOPerly sshsieeets Saves rt Ai ethn s Siete ease Patni ai eau eareieeay 14-9 
FNQDE Methods it, c2cec ccedestunvecesetdecesavsdacetstsnedehivnsoeetsdagcdeneradoiebedagstesiyngointetesouugeredeentedes 14-9 
Read from appropriate Channel ......... eee eeeeesseecsseecsseecsseeceseeeesseecsaeecsseeceseeeesaeeesaeers 14-9 
Process read Completion ............:eseseceesceceseeeeseeessseecseecsseecesaeeesaeecsaeecseeseseeeesseessaeers 14-9 
Close both open channels ............cescesscccsseecsseecssceceseeeesseecsaeecseecseesssaeeesseesseesseeeses 14-10 
Starilist SCHETALOM 26: tes santededesses cep eeteshdeset odes sent etedesceeey dees ated leds ect sceda ei ceeeebeebeaeet eg 14-10 
Deferred FNODE methods ...............cccscsscscossnseseessssesensoncecensnseecensusesesenseesseteseecsersseecsnnnees 14-10 
Handle:completed:l sti... 20s. atcteas est cae eho Sisk ee Bichon tak see Sieh oes atewe Baan an ee ts 14-10 
Process:a list tems scsicse. dese ceseccdaceacccdacoundessecancesasvandesessetceassuarceniva cons detecessacde ceaseeanees 14-10 
CAS Ye egectestiics octet cnet ste takers Mes dardep stat rue rath tee tates pat dee stern ete ds tates Oe stall Sarath aa Sty 14-11 
Class definition siccccccsesdevcsccstegeedset cesedsededeedaetcdvviceleseviaabccuy dead cdevdeeb cabeaded caevacee ceuedcvoees 14-11 
Property s..26 sect tte eh a as Se eat Rt eh a eh ited Mat oO Ae eNO a eet son 14-12 
FCASY methods sic. cciicteciesieccciesevtascesevees ceseedarceaescan conendancensacnucebvecne ceneceha cenvedaa cesaeedeenset ea 14-12 
Cancel PEQUeSt x. sssccesdeses dist setseededes edussussevevednssvepacouess votetsdueuetedstededstupedebendedesesupncobeste 14-12 
Read TEQUESEE icsecscccsecaeracsvececcee daaedceuacancenscdandesvedhades uedeedeaus dandeae dosbeabadevbearcdevssanccoeises 14-12 
Write TEQUESE aienied Able AR ed GU Recivte tah etek de aie hdl Muted iin deal ede tet ies 14-12 
Process read or write COMpIeCtiON «0.0... eeeeeeeeceseesneecseecsseeceseecesaecaeecsaeessseessneeeesaes 14-13 
Close the fle so ccecicedecectesscedenvenssvedaaes Deedee de de daeacenedisavusounsehlGedeea We eterenieedets eiuseee res 14-13 
Open a file sssertesovtteeaiydastgiseesteiphes eae Lee plaad ede gn angen ee aip eee 14-13 


OLIB REFERENCE 


Deferred: FOAS Ymethods esis: teeesdugsteectts deus cidsdevsleasduye ius sdees teases ceVadunedeadtunedes sdunedessinbeds 14-14 
Inforin: Of: Completions :..<csadascasieatic aadateatisiacswadariedusaniacsngatsesaaredatonsaneenlasedtess 14-14 
BOS YING oir os cnehieehiden test iocts ch guct boutcah Sigs auch saubicous Stes gues debeaeh sees auch casleses de soavehs ashesuhocwsavede aehhy 14-14 
Class:definition .ciAh aici cidcsiiincs Bonin tidi a dcadias eatin oaNaletehiaa sisal eceactede 14-14 
PLOPETY fess eves ices cies cavbedi eneits tas Sones evaeea chve cuss Be yonnih deverepaaynoetia ceupsvinguooeansduesdevacnneeees tubes’ 14-14 
ECS YNG meth odsyxc:iiostisvicaveailesriaciesattaissestbatoaniaioatiiaeiaoeatieonatiratcecetiaitis 14-15 
Read Pequestt:2.55.chicis icacaet sincegsoivaceuksiehcnebide acne odee ieee ciuksaehceteocaguvhocwatouseteeguekecataey 14-15 
Wile TEQUESt si cosss Jorapscccestieaacrtadeaconsvsauacs sostacmeatoaders Goldeceaspiatedasoseacousteets pvsmeacoessedeeaet 14-15 
15 File Lists ............cscssssssssssssscssscssssssssssesssessscsssecssccsscesscsssasssasssasssasssasssassssessnessnsssasssasssasssesooeees 15-1 
PLeCULSOLS ress vat cate Loss Ses vain cat Leck ot necalecte ties ots nxtndeedekuvk ats Gers tvedebins ace ce tetoate yak ous tuseeeabe tty 15-1 
Class: didetain 2:::sicsisasgiteieiiaeaien ei iva is nian sein aia cave Saini nein: 15-1 
IPS ETE VARs, ceca ssh Pave i eset Oi ait Sites tee oto va ueeat ety oft candeeste Mieaatescaeatete, lathes eat and stetoteaes 15-2 
Class definition » is. ccisctcustetudestisenics cated eed cstedevscabndes vedaodes scabedesds deed salideedusdigneasatiavees 15-2 
PLOPOLEY. Fetish Aire sist oan bbs oak chaeh skeet ch souk ctu painless caunteae e Hiutesh oaWhagea Hates caus see etaadeee dete 15-2 
PSELEVAR methods’. cciics.ccseiediceevscseceescedacensccauceesccdaseascddaseaucdda cosuccadecsucddssvatcaseedencessseetess 15-3 
Compare two records by pOinter .......... cc eeseeeseeecesseecsseeceseecesseeesseecsaeecseeesseeeesaeessaeers 15-3 
PNODE i eseesiicciete ihe aeons Aras iste aves ph era eaieale yan 15-3 
Class: definition is side ccs ih cectett ce. hudeeee vistc conductetes ies cena eves die oes Liem ieee deen c A 15-3 
PLOPerty Mires HsitsrSileaves eet ailentta trainee iste ashe ae ave RUA, 15-3 
PNODE 11@th Od. ois. c2: cadec eds gadasevevnces odes edae sve vedas sdeseddaa devodes otis olessta codesedpeteavvagecstelhyedeseae tes 15-4 
Han dl é errr scicsic.ccscciscteatedsataaeedvad cdevitan cdvedaededvviaes dav deed cdevdean Cdesdsndusevidsvegs viateseviaes cet 15-4 
Handlecompleted listises aces Git acetic eek Gate iene ee ee 15-4 
Process a list 1temis.s i csceivesesevleas cas tarceveisdacess ane eevdelacedcdaususvecdavesecsbavsaceseaesseasves 15-4 
IPS EEL fossa ted ses dite tet ocveest ste s tat ceeveeshatey hot cetteeste dey etetepec taste tee Set oeeieestedes eteyss Peet toy tosis eae 15-4 
Class Gefimition sicciccesicsecotveccndesecdarscevicnnces cans covecaveevsddaadenvadarden cdaaseeut dovdeatddevecabicenes 15-5 
PHOPCLUY. 5 ities sist esec bss dur obss cae btu See obnt oats Suet ove aun teativaunteas cas uesvotaatees audtesivaust ses gbntedus ans 15-6 
PSEL, 1eth Od Siz cvsdsseciveicss ceseiea eccegicaa Seve deans tevecaa ce edcdnses vecdaduawdcdaseaucdaaceaudessevancessevancedeeestces 15-7 
Tint G1 AlaSGs oe, codssivedtevess eotatevcesansexsendsneverdiea se sedlsavsieucs sxnsedasaviueieesduveleveuieetsbewiner aioe a 15-7 
Handle errors: .c.cisiccvacteeesiastics ane caused iancd deed eviaveederbavbetanieveisatdeabidevieveideibevvudenecevics 15-7 
Caricel list: but dit g® ..3 05, secs sees bie son eoeatones tect ot count sdun beste cee bead cguebtsboteetuntogs anebeeesstness 15-7 
Add a file Mame. si. ce..ssicedecesicctvs taatcces ccauceededacesucdausdesccdasesvecddvesucddadeaucdsnevsnccueenstcesves 15-8 
Add -asdirectory Narmes.... fs. sd5, sce A sete testy easbedesotegactpststedesetetanvasustedveedeborepststedpetetorepeas 15-8 
Procéss end..Of a SCAN. isi cecscesticveaces aevkcdbesseccsecdusiesbesandeevederdeseesardesecderdevvadendeaeddensesvecs 15-8 
Build filename Dist... cee cc cicess cectetd owes usa cee diid oeesdant sen caudd oevstaeasercddesedeiacesuaaducdershaedes 15-8 
Ascend one subdirectory level..........eesesescecssecsscecesceeesseecsaeecsacecseecssaeeesaeessaeesseeenes 15-9 
Deéscenid:to: a: subdirectory atu, cecc.z. poten exes pent hte oteg chp sent ote p odes th eaiet eves edeeecegpietedp deeetey nae 15-9 
Sela MEW pathsstatoch ists held ee diene teks bali Ardea eine 15-9 
pensera Tlelistitenie ats ciate litte ctee ihn cee eit eed Beton eed ees 15-9 
Select anode list entry.:.scce:cnrbs cick elie nea wae dinar aie 15-9 
Ascend to the drives level ............:ccccssscceesescceeeeseeeeeeececeeeeseaeeeeesnaeeeenenaeeeeseneeeeeenaeeeess 15-10 
Set/clear a file: tagh. cc: cavaiyitesyshtaeyieideyeeliehighe deere ied peel taeda bd een 15-10 
Geta: tas eed He eke oat Scat sa sees ictacie aad ste ae oat hated acters Hag ems alslor shaten Gastete tea 15-10 
Set the file list: Order on. ccc.ccscccsaseueicssevasccssevancesesvascesedearceveicarccassvancensicancepscetnceswecaa coves 15-10 
Deferred PSEL methods 
Process the completion of list DUIIGING........ eee eeeeeeeeeeesneeeeeeceseesaeecsaeecseesesaeeesaes 15-11 


16 File Management Classes.............scsscccssscssssscsssecsssecsssscsssssssssscssssssssssssssssssscsssssssssssssssonseoes 16-1 
PLECUISOLS..ssccs,hsascests shi Sydizasseusctecteidaastontactacanhataspossasteaeadsassestesisaaysesasseanastaavengaess ove 16-1 
Class diasrarn 2.0. fcsitesie hihi ceette dst Subs seis hhh delaeed Rekhaks Helos Eh igaataeed 16-1 
Class defitittioness 2. sieis45.:.situstsaniese Aedes eens es desiasedes A acsestavitess asbestasioers ents 16-3 
PLOPOEey. « csss2iis ccs saves revs shee Ped sanes seis tevsdve Steussua steve dvecesvesvecduve ieasevyaseyedevasussevsacusstuusens Seevses 16-3 

FMAN method §:c.ci.s2sssccctsstsctasdavientegianeadaapentactacdndasapensactasdandaihtentantaseendsttesteataoeanda eens 16-4 
Initialise the file manager’, 2.05: .s.s0ebssehagieeui cg chteks goheouh sa peaehsvehe quienes oeesaven lhe dveeeuboeehevuas 16-4 
Cancel an outstanding request ......... eee eesceessecesseeeseecsscecseeecesaeecsaeecseeceseeeesaeersaeers 16-4 
Copy files iss siete siv. sees scksson fh Rasteos Taba teesr tain abeTesr ta Algae ev eos Bi 16-5 
Delete: filess.iscirissiccasistiosesdaviccszaciiosandsitois to canesisgs.teataneasastagesteatpeasasiagectastaceabentveaetesy 16-5 
Retiame filess. i303. sectioned id beat ded Se Shes Babee eh 16-6 
Make aidirectory treesesi: i i.ssh- asiesseatises AnphisisssniebeAspdisscnipions sattesessehSdehae aula ae 16-7 
Delete a directory: structure ssi.c.ic:20ssceisissecsistevseet sees eats PuboevbioeesseinPubeevtstevssesndubeevistebets 16-7 


CONTENTS 


COpy. As CEVACE 2.5 feck zeus Fou stehesees Bove tae Peees fens Pevetues dike ste Febvedussdees Hesgdubs tevstebessedvbstoueeeent hy 16-7 
Formataidevice ssc: iasentetottiaiasscndsisosstesiacontadacelesiaacuntaaaceieseuslackeaeiaaieendeteauicarstom 16-8 
Nate ai evice sre. teicessctt fescict Sevsanchseetonch srvsancs sdesetengevaateneautonehssceanehcasneensiveenensactesensies 16-8 
Set file attributes: si. d sca tiheee wtediescesanie needs vaisteteds ovsediae vada eve adeeseetidiassenaoeandes 16-8 
Deferred FMAN ‘methods ic. 2:ccccsszheecect sing cosadi ne savaceketeradves casa doussuadieasova es sduustewesesateeerciaaes 16-9 
Processin ¢ completed s:isi-s.sdesisssudshicasscsinacssdachcostgaasoeaicathcnatsauocangaaigesteasiocanaeelasienecs 16-9 
Processing a Tew file's: 5iic0is sessed ooh ak fegeek oh ahi eek Sake noe a ek aed 16-10 
Section of processing completed ...........cesceescecsseeceseeeseecsaeecseeesseesesaeeesaeeesaeesseeeees 16-11 
File @xAStS's 225 253 cscva cies sak sdegecues Pevsdca Sdeeeces sduvedes laces sebe Sensbene Fuvbatbedsidaebetedbsibesesstesesulyceeeds 16-11 
Determitie-€rror respOnsess..icsiss-ssdavicissealanssadaheasteslaseaudackeasteaiaceabde seas teaioes sleboasteayst 16-11 
FIMMAK., i, hop ised al ee Re ee Ba eee lea iii ei lied ch eaboths 16-12 
Glass efi ti ON: sess. retebis esas decease vavde ae secedias cate biatsvaedied sais ddaddesedeea obsedkc wsetias svaeeiacees 16-12 
PLOPELLY: sosci cvs teassetstiessc¥s vl sctathvsstescevsccudesvssevadeessevadevssevaduessesdteesauts feunebsteusets sfevacnd eves 16-12 
FIMMK methods 31...tisccrsacsieccstesccesacaitceateassteassattataacneeussanearssausberadascensenaeenacnieoensaaecs 16-12 
Process a make directory request ...........:cesecesssceesseeesnceceseeceseeeesaeecsaeecseeceseeeesaeessaeers 16-12 
EMEMD s.3.so3 erin hisdstneb actin kis Anita Manion Asoosio sti Aateas Vitaos Anat siaanios Aaetaay 16-13 
Gl ass:detim ti Onis cogs 305 bch eens Beiks fad sacks cot subs Ook ache cud Saved ecbaanes Cov tava fubatens Cevioveetenscueesert beds 16-13 
PLOPOLey: sichisisesscssssisseeadshessteshacsudaadeasteseatesediatsoste tassesbdaaieasteginsushdtaoeckasiateedanveesietss 16-13 
BMEMGEP methods x. <: 5st sis 265 Soe ece Se cnckes sazteceh Fasacves santeaeh tana peu keancountas rem dekeweicice oeaetebenctoees 16-13 
Process.a format request:..\.icssco BA sih sti Asis shes Auhasdeaiohahodn shad 16-13 
Process formatting error as ts2. esses c, erties Ba ertitewsievs Ga stus teeta seis tastevet 16-14 
EMSGAN #32 iss .cpede5shteasas lata staansoesnaannpeatastvoeasasea sasbeasvevanases estan ieaes Suess aeatapeeenieeapoeateanensigenss 16-14 
Class: detim iti Oni se. ec. sock cac ares eet se vccnes Sasnecehonenenenes ou caek sacs coentunn cawk gece ewer eoutveseeueceaee 16-14 
PLOPCLEY oss ssdess aati eatiiss Mattias A AspNi aia ketiseani i hAviiiari bn Anni b antes 16-14 
PMSCAN "methods we: sacs ase i} savgscave sue del stuneceds aubedet stuns codhatke Subscene Cevacivebevabeusseva cevedehacetessiaces 16-15 
PLOGCESS AN EITONS, e26scssadavasentaacscaassansoeateatagarsaasoeeiaa sues sulanseestad avasadehedebaauvenestenaeseleneas 16-15 
Wext: fil@ Tames c..0s2 csi: seicart cosececnd oeneuss Secegens donanen asi ceeacd dents a coehgoekewente ce erelgbenaieusicee 16-15 
Next.diréctory: Name-..25.%\sisii hen Msinistiaeiet Mais hain Aaieatt aid Aacmeatndi Macias 16-16 
Hrid Of subditectory ss.:.0ssic:cots2iess o2zideovstawss dasuih ete thors bs thadeaatvesesds dibeeiateesiads hs tevietes 16-16 
Scat: Completion? sy: sssesds.sc ceases cass scatisioeandsi.tesfeateoeatasiage desig easitasseelaaetestenenbasheesl 16-16 
EIMISRG sss bette Seabee chats Sicaeasbcg svat ch heen baad soya cus oeeuboad caubanes Saou oes cauhe Si Siesgocnsaababedeeeseen hte 16-17 
Class definitiGiiin ssscsaceess hai oecseee desea aveaias dh tesati adaes dadoseat vveeee Abeseed oesiens tesactas os 16-17 
PLOPOLLY Sick sevseees cad ceesd eh stees cea atevedeentays svandevs iealeeys reyldevs ius bevya sues Zevsaes Seeyseus SPevsats Seevoous oPey 16-17 
PMSRE methods: .ctsctesiccustsaccatesiacdesdastesatonlecceadasecctaalaccuadateavtaaaceastatearsanaceudatearantas 16-17 
Process: a réad: Complett Oth: 25.254. isievesccessbel aut eotacsshatehaies eouncesscveb badesuecessotehsdehewssonosens 16-17 
EMTARG #3. cM Ssiseistes dio Aoshi shane kvoadiadwa oa kas 16-18 
C2 Fil G10 |W le) 0 Oarmerep eer mere er tree pre en rreerertertcrst rete fr crer pret irre nce orne etree entrar tenes 16-18 
PLOPOLey: vicisassasgceassisg vasa sascvelatus oshesasoassetastosbatasdssaadasaaybesassanned as ovata sesoehadesseatesuaveeiaaa® 16-18 
PMT ARG methods successes ccuetieis Secdeck asiaess icadecheaguevensdeadecheaguesunsdeadevkeshewevcdeedoctedebeonsodes 16-18 
Process a wiite‘COmpletion 4. jiscizs-c.cuscabssshaesdeacithe sees boepseusdtpacess das esesedte,cvapdenesesseuascs 16-18 
File: manager exarnple tenis: icc. 2eisziveie Saves cosbzividel Jaevecustdivsdeh Suavesuetzevsieh Seeeessettuvetel auvsesis tubes 16-19 
17 The LOCS Local File Scan Class............ssssscsssesssessssrssessssssesssessscsssesssesssesssesssesssessscsssessoess 17-1 
PLECULSOTS esis seceigd cess casvace sedan cess dus sacs uceuaevan cuanecancesa seen dsauecae cous sues dvanecaudeuecuavdasnuaaneeseseny 17-1 
Class etinitiOns oie: ce. cesses cseheedesediaecesudtedenichseceeadhsecenadtaeveradtesteneddaczenetiesunnerdasunsceedoes 17-2 
POPE ty Si eseesseecbe asian t ech bee vaee dees Deda w aes ddoude bude vaaen qdeubeobudancane uevvaveusdevieendeesbery 17-2 
LOGS Methods ec seiss cot ces. s idee aed aaka ibaa eet saath tae Woes etd eens iota oem ae ian 17-3 
Perform: a: file:Scatt ccccicsisseciecesiiveiecditeesncessecaecdidesanieasvste ceieudavecaeseae convene cesveete ceaveaacens 17-3 
Check file name:match soo: chic cuceliescasecseecesediescosevetedetadiya cobacndedehutieacunartacdegedesvcusereess 17-3 
Deferred LOCS methods: :a.siscsccceisst cessackiecsvdett cdevicabecovdeae ceeyccabasevacea cdevecsbses veces caeuecsbecedess 17-3 
Process atile name ws. icciessccse, cbcteees iectecneaitlawe cueeean clidbaaes beeeaan cela aes eeeesenedesatea seeesde eds 17-3 


OLIB REFERENCE 


TS System: ServiCes:..ccas.sscocssessnnsedessnotessssscesosdoasessesondesendensesensandesendacsesesenodesestsoveeansevesessessnssssenes 18-1 
PRECULESOLS 2 oiys acted cecpestiyedets fa veeo ative date Coa stepaveyo denn deg saueaderonate dea stuusctpeteee dees tapecepedeneteeoes 18-1 
SYSTEM ssciiiintin aaah euisiaR ani ete ae aia loa pane elders 18-1 
Class definition) 68 Aen aside ded eatitbhed abide la aie 18-2 
Property, Hi.cren eset est iti biel hott as eh ais eae eae, 18-2 
SYSTEM Methods. i... cs cnc heerseduvrestadidecssedisceakadededecadeas cotadededededdctatecstadedestinta dedacsevserciaes 18-2 
Initialise si cvvcscvieseesercesecuerdcvvisnedesesderscevisandens sland cvuedandeesadaades dade deauedaedesud dundeanidevesavadene’ 18-2 
Coritrol. 1Compositlonini 83... Sites het ea al Gl Meena Gata 18-2 

Set link paste server 2isi..i4si.i Ass eavaestis dus eatasies Rita diate dareraiee 18-3 

Get link Paste :SEVEI sos. f55: ec seet ef geteaeuhy poet ede eoten Sued beet ites teh ieh poiat owe, otep ee daeet eas tense eas 18-3 
Run an application by file Mame ....... eee eeeeeesseeeescecsseeceeceseeeesseecsaeecsaceseeeenaeeesaes 18-3 

19 Inter-process Commumication...............ssccssccssssccsssscsssscsssecssssssssssssssscsssscsssssssssssssssesssscssssees 19-1 
PLeCUESOLS<: 34 ssatcscicestesierehiaekeestastuecetauveasbes Waa calcbavoavonstegsaacsuvenssasteouasearaeevanateceoneauseecs 19-1 
Inheritance: tree: p23 ces tae es hee keeeasconeeck ene cab ee rhc toch ace lees aceon coameidestectiarenetesed 19-1 
IPCS iiss. ttisid issih tie bienaatien Aoi Asap aliats eisai Ais aighee Aas ad 19-2 
Class*defaniti ons: 2s. cerseiie teens cist sees dek ceeus evel cevades dats cus bcuva (oh cdvxs cae ouweded doves cod duwedeh olaxeees a 19-2 
Property sss chs cidseseessasusscsadeeseecaacistsanaesss sadeciacsssdeasssssesuasovad saveasdeseagebdgaseeckesuaosandaess sae 19-2 
TIRG@S, Methods rics f 5203 cccsect 5 cnctet cencned re nuevos sco cves eynucteseavlcwalee a cteressleredonseeres avnguen sieneeensinees 19-3 
DeStloys sssstoeSAsisids eh Attia Aisa ai snide aslas doa as 19-3 
Tint Ala S65 c2iosscte.vas ete dcoes. te Seendete te oseev' Sena dea dese ae una Gav tbaxseaw dus Cava dyaeeede dune davbtueeee ds tan edes 4 19-3 
Olleue a Messase Tea! sis.cs.shcsssceus sseses..oinadeus seeeeathodesss vs seateatsedelauaceabasieaasteaeaceasasesease 19-3 
Cancel readirequest cis: cei soi abies sence ia heh eared Ske Pen eee A sete bach ad Leeds nb 19-3 
PLOCESS:AMESSA RE oii ss ERs castes st Astesssosstec si dasteics ove teana hsvoasosseasenssemesazoves asset 19-3 
Hain dle error set. sis. ccnaaseiet steseseds eeeet ctevesetcvec tek tees eeiceberet cdeysawacvesdetddeesenttevertes ceeeste 19-4 
Add item:to Server Queue its.i-s.sccacsendasseeeagieaceendatcasteaiaveoadaaiesaiscentlosdoestesitentleedsetass 19-4 
SERVER eoiititissrccshoei Siohesel te ohiesdbges ewuboees ores acdeaul onus ovens dekgaud sess ceebsekeuth sevouevnsdeugoel caveperlbev ih 19-4 
Class de tanitiOniessisfacseiccitus cestissdetadins sets duas dead ea ottadiaideasda va csdeseae edediaa daseuasatosiendeees 19-5 
PLODOLUY, ¢ Peszccvsccss suis cetedeossens teen suetescess desuseedevecessivvedeidveserossceveseisduvesevdevesnseansesessoessee 19-5 
SERV ERsmethodSis.::.scfardesnc cess sie caitast concsutcataaeeccnncaniceaisaunt caxsaneeaasagine uacaeeoaanegeteucaescans 19-5 
DESTLOY Ss sisi f5ch cosh achcistsdetbvciodsadouisietdockscoheuzhe dotouckadeedusbedssdustod gouuute dvsduekedysdechsgeatockegevach 19-5 

Wii tialaSe.2s 8 hte tetatitien he teat enon ectateaein dana erie bee ee ea ees 19-5 
Haid error ss a2. beucteve dea aeeeaee Rive dea lee geresa deve dun idevstedadebetue baegs dull dees des Saeeaceea tuesdeabeeeede 19-5 
Deferred:SERVER methods .ci.:gs.sosstesiarsendsecstesiatsentasavestasinccuadaaoeutasaccendanseeetesiaccandasiess 19-6 
PLOCESS' A MESSA BE io. oess cca cces seve goes Seunsoes scud vous coues bua cowdgwnd cous Sout cevb even ceva snub desbeuus cesssues estes 19-6 

20 Link Paste.............sccssccsssscsssscsssecsssecsssesssssscsssscsssscssscssssssssscsssscsssscssssessssssssssesssscsessesossssoseees 20-1 
Precursors. steseik aia aie ee a 20-2 
Class: diagratinns 05 ac sn eet Beit ee ited AOS eat eA BL eA et es 20-2 
LINK CIs ses Saisie Sis eel nei eh ee av a vac eh eral 20-2 
Class: defirinti Onn $5. 5.505,.05, saetgseet scavetessceebaetevese Sodeceesintesutete sostesinteve de doseeep tate deverseesecet ed 20-2 
Property: <6 sischceistaibesivausg lets tesivd shed eed Ree heehee een avin eeobed peesede 20-2 
LINK Clim ethod singe scccisin Jos kit ocbciesd seat odestlen oh ated ted alate dened aided inten ated ts 20-3 
DOSthOYei gs faves hehiccgsvecvdesicted eis ta edea aces ccane tar deiatenseeps tear ieaeceveesi desedeaaeabeny ee ninereeens 20-3 
Trnitiate a tramsaction...........ccccceeccccessscceeeeeseceeeaeeeceecececseaeecceseeeeeeeaeeeeseeeeeseeneeeeeeeeess 20-3 
Request data. :. icici ceisaitccesient ceussae cauiaad canudcboesuvlavecuardea besendesbesas deveiderdevvigergesbeaenaeessde 20-3 
Terminate a transaction ........cccccccccccssssccceseseeeceseeeeseneeecssaceeeeseaeeeeeaeeecssneeesseeeeeeseaeess 20-3 
LINKS 3c oisisiay ad eis eee ets eve ei av ian aie aval ai avers 20-4 
Class: defini ti On iv. cccescceeceessleztedecoteceteessntededadeGertescatededs tag eierd catatedadadevisedarstageteaeiarbendss 20-4 
PLOPOI ly. ss cceccsedniecitecbeteeedaeescatec tobe va caentehbecsvdeh uedevdesnedevdvstensteebuesvvdueb oh esesvedevdeeciebeabeds 20-4 
LINKS Veto sooo cscsien sot AG cectuct ah ese a davtue oat atten teed haste thetsd aitted tect abesied ate 20-5 
Initialise ss ievissreteis shai eStats nieces ei siesta ei baee en elie erate 20-5 
PLOCESS ANINESSA RE cceersdesokatCocgecetevesatateves oust oti vedatccveecatetucodsteuersesedupedetbecgeeutetheedessecerts 20-5 
Deferred LINKSV methods ............cccccecessccceesnceeceeneeeeeeeaeeecesnneeeeseaeeeeesnaeeesseaeeeeessaeeeeneaaees 20-6 
Set data fOrmaticn wo cv cts etetse ite aoe ae teen Gale eh is eae Cee ace 20-6 
Provide datas ccssivcviiic tied ec viadecies cedevsav east tecdeaehu ceveadas cobs tenucenes abesd cchbees wedi eeletaav ees 20-6 


CHAPTER 1 


INTRODUCTION 


This manual is a reference document for Psion's OLIB library. It provides a comprehensive guide to the 
library and documents the classes, methods, properties, inheritance hierarchies and other information 
essential for understanding and using the library. It assumes familiarity with the concepts of Object 
Oriented Programming. 


The Object Oriented Programming Guide is a useful pre-requisite as it provides the necessary background 
to Object Oriented Programming as implemented at Psion. It can, of course, be read in conjunction with 
the OLIB Reference manual. 


The OLIB library is supplied as the olib.dy] dynamic link library in the ROM of all SIBO machines. It 
contains a collection of classes, built on the services of the PLIB library. 


OLIB classes provide a range of services that are independent of the user interface used by an application. 
For example, they include a number of classes for creating array type objects which possess sophisticated 
behaviour. 


Use of the OLIB library allows complex applications to be built quickly and reliably. The OLIB object 
classes can be used directly or can be subclassed by any application code. They are both subclassed and 
used directly as components by the user interface libraries (for example, HWIM). 


Each chapter in this manual contains a description of either a single class or a number of closely related 
classes. For example, the Variable Array Classes chapter describes a number of classes that implement 
different types of array, each with a variable number of elements, while The TIME Class chapter describes 
a single class. 


The description of each class follows the same format. It includes the purpose of the class, the hierarchical 
relationship of the class to other classes, the actual class definition, a description of the property and a 
complete list and discussion of the methods. References to relevant manuals are included if any pre- 
requisite information is needed. 


The first chapter contains a description of the Root class, from which all other classes are derived. It is, 
therefore, a required class in all object oriented programs. ! 


OLIB object classes provide services which include: 
e data storage in a segmented buffer 
e arrays with a variable number of elements 
e basic text editing 
e event management and scheduling 
e time management and timers 
e = file management 


e inter-process communication 


! Tt is, however, permissible for a category that has no intrinsic dependence on other OLIB classes to 
define its own root class and thereby eliminate all dependency on OLIB. See, for example, the Building a 
Dynamic Library chapter of the Object Oriented Programming Guide. 


OLIB REFERENCE 


Using OLIB classes 


An application (or DYL) that either subclasses or creates an instance of an OLIB class must declare an 
external reference to the OLIB library in its category file. If, for example, an application's category file has 
the name myprog.cat, the content of this category file must start with the following lines: 


IMAGE myprog 
EXTERNAL olib 


This ensures that, amongst other things, the defined constants representing the external category numbers 
for the OLIB category (in this case caT_myapp_oL1B) is available to application code. (It is, in any case, 
required in virtually all category files, to provide access to the root class, from which all other classes are 
derived - see the later ROOT class section in this chapter.) 


In the source code of the MYPROG application, an instance of an OLIB class - say, of vaszc - would be 
created with p_new (or £_new) as follows: 


p_new (CAT_MYPROG_OLIB, C_VASEG) ; 


If myprog.cat defines a subclass of an OLIB class (say, the class susvasEc) this would exist in the local 
category. An instance is created using the local category number cat_mypRoG_MypPROG, as follows: 


p_new (CAT_MYPROG_MYPROG, C_SUBVASEG) ; 


Similar considerations apply to instances created by means of £_newsend. 


Notation 


Throughout this manual, all references to the Series 3 should be taken to refer to the Series 3a and the 
Workabout, unless explicitly stated otherwise. 


Names 


Except in class diagrams, a class name is always given in upper case, for example varoot. 


The method name in the title line of the description of each method is the defined symbol for the method 
number, without its leading o_. In the body of the text this name, in lower case letters, is used to refer to 
the method function (or more simply, the method) whereas the upper case name refers to the 
corresponding message. Thus, an object's dest roy method function is executed when the object receives a 
DESTROY Message. 


Method function prototypes 


The description of each method contains a function prototype that specifies the nature of any return value 
and the parameters with which the method is called. The parameters exclude the object handle and the 
method number. 


For example, a method for the class var.at with the title line: 


VA_TEST Compare two records by pointer 
and prototyped as: 
VOID va_test (UBYTE *precl, UBYTE *prec2) ; 
would be invoked by: 
p_send4 (hand, O_VA_TEST, precl, prec2) ; 
where hand is the handle of an object of the class in question. 
This corresponds to a method function declared in C source code as: 


METHOD VOID vaflat_va_test (PR_VAFLAT *self, UBYTE *precl, UBYTE *prec2) 
{ 


} 


1 INTRODUCTION 


The & symbol 


The enter and leave mechanism (which uses p_enter and p_leave) is commonly used to implement 
structured error recovery. See the Error Handling and Error Recovery chapter of the Object Oriented 
Programming Guide and the Error Handling chapter of the PLIB Reference manual. 


Some methods (the vast majority of destroy methods, for example) can never fail and will therefore never 
call p_leave. The title line of a number of the more significant methods of this type are marked with a 
leading © symbol. 


With the enter and leave mechanism, a call to p_leave should only occur within the protection of a 
p_enter harness. If p_leave is called outside a p_enter harness, the process will be panicked with panic 
number 47. 


The p_leave mechanism and its use in method functions is discussed briefly in the section on Structured 
Error Recovery later in this chapter. 


Long parameters 


A small number of OLIB class methods require a LoNc or a ULONG parameter. For the reasons explained in 
the Introduction chapter of the Object Oriented Programming Guide, the message-sending mechanism in 
TopSpeed C does not support such parameters and they should be passed as two InT (or UINT) parameters, 
where the first is the least significant word and the second is the most significant word of the data. In such 
a case the actual method prototype is always followed by a conceptual form, illustrating the intent of the 
parameters. 


Class diagrams 


To illustrate the inheritance and using relationships between classes, most chapters will contain at least 
one class diagram. 


The notation is a subset of that used by Grady Booch and described in his book Object-oriented Analysis 
and Design with applications (2nd edition) with two minor changes; 


e classes which are referenced, but not described, within a chapter (i.e. classes whose full 
description lies in other chapters of this manual or in a different manual), are underlined, 


e the diagrams do not distinguish between 'has' (aggregation) and ‘using’ (client/supplier) 
relationships. 


Also note that ultimate inheritance from the root class is assumed and is not shown. 


Class hierarchy 


In understanding the structure of a specific class, remember that methods and property are often inherited 
from a superclass (or superclasses). 


While a class may contain new methods and property, it may also re-define methods inherited from a 
superclass (or superclasses). Note that methods in a superclass can be what are known as deferred 
methods. 


To help illustrate these relationships, each class description in this manual is accompanied by a diagram 
which shows that class and its superclass(es) in hierarchical order. This diagram is placed at the 
beginning of the class description. 


The diagram consists of a series of adjacent columns. The rightmost column represents the class being 
described and will be marked by a double line border while the column to its left represents its immediate 
superclass (if any) marked by a single line border and so on up the hierarchy. Each column is headed by 
the class name followed by two boxes; the first lists that class's property and the second lists its methods. 


Deferred methods are separated from the preceding methods by a blank line and are printed in italics. If a 
class re-defines an inherited method, the method name in the appropriate superclass is written with a line 
through it. 


OLIB REFERENCE 


For example, the following diagram would be included in a description of class cccc subclassed from BBBB 
which itself is subclasses aaaa. 


property_1l property_4 
property_2 property_5 


method_a method_b 
metheod—b method_c 
method_d method_x 


method_e method_y 
method_z 


method_u 


In this illustration, method_a is supplied by the superclass aaaa, while method_b is replaced in class BBBB 
and further replaced in class cccc. Another method, method_c, is introduced in class BppB but replaced in 
cccc, and so on. Note that method_u is a deferred method. 


The root class from which all classes are derived is assumed and will not be shown in the diagrams. 


Structured Error Recovery 


As mentioned earlier, the enter and leave mechanism is commonly used to implement structured error 
recovery. 


Use of the p_leave mechanism 


In general, you should assume that all methods NOT marked with the & symbol (as discussed in the 
section on Notation) are capable of calling p_1eave, even if this is not explicitly mentioned in the method 
description. In some cases, such as where a method calls, directly or indirectly, a deferred method (which 
is supplied by a subclasser) it is not possible to specify whether the method may result in p_leave being 
called. 


In the event of an error (such as out of system memory) occurring a method may: 
e call p_ieave, passing the (negative) error number, 
e return the error number, 
e either call p_1eave or return an error number, depending on the nature of the error. 


Some methods call p_leave (0), which has the effect of returning from the p_enter harness (with the 
return value zero) without signalling an error. This is used, for example, to provide a normal exit from a 
deeply nested function call, without the need for a zero return value to be passed back through the chain of 
calls. Intermediate functions in the chain may then be declared as vorp. 


Some method functions that may call p_1eave are declared as vorp. One reason for this may be that the 
method forms part of a chain, as described in the preceding paragraph. If user code were to send such a 
message within a p_enter harness, the value returned from p_enter would be indeterminate if no error 
arose. The solution is to construct a shell function which sends the message and then returns zero, and 

call this shell within a p_enter harness. The call to p_enter will then return either zero (if the method 

calls p_leave(0) or it executes to completion) or a negative error number. 


1 INTRODUCTION 


Panic numbers 


See the Error Handling and Error Recovery chapter of the Object Oriented Programming Guide and the 
Error Handling chapter of the PLIB Reference manual for a discussion of panics and panic numbers. 


OLIB panics a client that attempts an illegal operation, using the following panic numbers: 


Record in flat variable array is out of range 

Number of record to insert new record before in flat VA is out of range 
Attempt to set capacity of flat VA less than current number of records 
Number of record to delete in flat VA is out of range 

Record in segmented VA is out of range 

Outside range of segmented buffer 

Tried to delete outside segmented buffer 

Record in string VA whose address is sought is out of range 

Attempt to set capacity of string VA less than current number of records 
Number of record to insert new record before in string VA is out of range 
Number of record to delete in string VA is out of range 

Did not read correct number of bytes from resource file 

Image fails to contain built-in resource file 

Stray signal death in Application Manager 

Request to clear area outside character map 

Bad type/length binary file record header 

Read on serial port already outstanding or read buffer not allocated 
Serial port read buffer too small for requested read 

Write to serial port already outstanding or write buffer not allocated 
Serial port write buffer too small for requested write 

Read on serial port outstanding when tried to see no. of characters available to read 
Read on serial port outstanding when tried to flush serial read buffer 
Read or write outstanding when tried to set serial port characteristics 
Control to set/get not supported 

OPL translator invoked with empty command line 

Unrecognised code for setting the console 

String passed to consol is too long 

IPCS Message read failed 

Stray signal death in IPCS server list 


CHAPTER 2 


THE ROOT CLAss 


The root class is the ultimate superclass from which all other classes are derived. It provides the basic 
behaviour which defines a class as being an Object Oriented entity. It contains property which is, in effect, 
the "hook" by which the operating system can keep hold of an instance of a class. 


A class must be subclassed from either an existing class or the Root class. 
Class definition 
Defined in category file olib.cat (generated header file olib.g). 


CLASS root 
The ultimate superclass - all other classes have root as their ancestor. 


{ 
ADD destroy 


PROPERTY 
{ 
P_OBJECT pc; class link 
} 
} 
Property 
root .pe The class link. This should not be accessed by any subclass. This is a data 


structure of type p_oBgect which is defined in p_std.h. 


The p_oBuect structure is as follows: 


typedef struct 
{ 
HANDLE hcat; 
HANDLE hclass; 
} P_OBJECT; 


where heat and hclass are HANDLE (a synonym for 1nT) data types and have the same meaning as the first 
two words of the p_cuass data structure. 


For more information on the underlying mechanisms of the Object Oriented system, see the Object 
Oriented Programming chapter of the PLIB Reference manual and/or the Introduction chapter and the 
appendices of the Object Oriented Programming Guide. 


OLIB REFERENCE 


ROOT methods 


J DESTROY Destroy the instance 


VOID destroy (VOID) ; 


Use the EPOC O/S Libbestroy system service to destroy the instance, together with all component objects 
that are marked for automatic destruction (by means of a PROPERTY n declaration in the class definition). 


The destroy method of every subclass must, ultimately, execute Root's destroy method, either by calling 
the root_destroy method function directly or, more usually, by supersending a pestroy message to the 
ROOT. 


CHAPTER 3 


THE TIME CLAss 


to_set 

to_sense 
to_add_years 
to_add_months 
to_add_days 
to_add_secs 
to_set_format 
to_sense_format 


to_get_sysdat 


The main purpose of the T1ME class is to convert from one representation of time to another (where the 
word time is used in the general sense, to include the date and the time of day). 


The Time class stores a current time within its property. Conversion is done by setting the time in one 
representation with the to_set method and then retrieving the same time in a different representation 
with the to_sense method. 


The time class "adds value" to the basic PLIB functions by: 


e using its stored state (the current time) to provide a more convenient interface to changing 
between the three PLIB representations of time (system time, P_DAysEc and P_DATE) 


e converting to and from textual representations of time (this is not provided by the PLIB 
functions) 


As well as the methods associated with conversion, there are methods to add a signed number of years, 
months, days and seconds to the current time. 


The time object stores a current time within its property in a p_payseEc struct which contains: 
e the number of days since January Ist 1900 (day 0 is January Ist) 
e the number of seconds in the day 


The number of days is stored in a long and can represent dates over a range of about 11.7 million years 
from year 1900. This range of validity is larger than any of the other representations supported. 


The property also stores format information that modifies the textual representations of time. A subset of 
the format information is used to interpret textual representations of time. 


Although the method descriptions which follow show only English time and date text, the actual text is 
language-dependent. (See the Language and country section of the General System Services chapter of the 
PLIB Reference manual.) 


See also uTImE, the HWIM subclass of TIME. 


OLIB REFERENCE 


Precursors 


A knowledge of the PLIB/EPOC time and date functions will aid the understanding of the T1me class. The 
chapter Time, Timers and Dates in the Plib Reference manual contains a description of the basic 
PLIB/EPOC time and date functions and the various formats in use. 


Class definition 


The time class subclasses root and is defined in the sub-category file time.c/l (with generated header 
file time.g). 


CLASS time root 


{ 
ADD to_set Set the time in a variety of representations 
ADD to_sense Sense the time in a variety of representations 
ADD to_add_years Add years to the current time 
ADD to_add_months Add months to the current time 
ADD to_add_days Add days to the current time 
ADD to_add_secs Add seconds to the current time 
ADD to_set_format Set the format for string representations of time 
ADD to_sense_format Sense the format for string representations of time 
ADD to_get_sysdat Get day/month/suffix/ampm name or system format 
CONSTANTS 

{ 

SET_TIME_SECONDS 0 

SET_TIME_DATE 1 

SET_TIME_DAYSEC 2 

SET_TIME_NOW 3 

SET_TIME_DATESTR 4 

SET_TIME_TIMESTR 5 

SENSE_TIME_SECONDS 0 

SENSE_TIME_DATE 1 

SENSE_TIME_DAYSEC 2 

SENSE_TIME_STRING 3 

SENSE_TIME_DATESTR 4 

SENSE_TIME_TIMESTR 5 


SENSE_TIME_FIELDS 0x8000 


! Field types 

FLD_TIME_DAY 0 

FLD_TIME_MONTH 1 

FLD_TIME_YEAR 2 

FLD_TIME_HOUR 3 

FLD_TIME_MINUTE 4 

FLD_TIME_SECOND 5 

FLD_TIME_DAYNAME 6 

! String format masks 

PR_TIME_DDMMYY 0x0000 

PR_TIME_MMDDYY 0x0001 

PR_TIME_YYMMDD 0x0002 

PR_TIME_DATE_ORDER 0x0003 

PR_TIME_NO_DAY 0x0004 

PR_TIME_NO_MONTH 0x0008 

PR_TIME_NO_YEAR 0x0010 

PR_TIME_MONTH_NAME 0x0020 

PR_TIME_SUFFIX_NAME 0x0040 

PR_TIME_DAY_NAME 0x0080 

PR_TIME_NO_CENTURY 0x0100 

PR_TIME_NO_SECS 0x0200 

PR_TIME_AMPM 0x0400 

TY_TIME_DAY 0 

TY_TIME_MONTH 1 

TY_TIME_SUFFIX 2 

TY_TIME_AMPM 3 

TY_TIME_FORMAT 4 

! Buffer capacities for strings, including terminating zero 
LN_TIME_DAY_NAME 14 Guaranteed max buffer size for a day name 
LN_TIME_MONTH_NAME 14 Guaranteed max buffer size for a month name 
LN_TIME_DATE_STR 48 Guaranteed max buffer size for a date 
LN_TIME_TIME_STR 12 Guaranteed max buffer size for a time 


} 


TYPES 
{ 


3 THE TIME CLASS 


typedef struct 


{ 


UWORD flags; date and time format 
UBYTE dsep; date separator 
UBYTE tsep; time separator 


} SE_TIME_ FORMAT; 
typedef struct 


{ 


UWORD fld; field type FLD_TIME_XXxX 
TEXT *buf; address of field 
UWORD len; length of field 


} SE_TIME_FIELD; 
typedef union 


{ 


TEXT *t; 

ULONG *1; 

P_DAYSEC *ds; 

P_DATE *dt; 

} PT_TIME_DATA; Address of time data 


} 


PROPERTY 
{ 


P_DAYSEC ds; days and seconds 
SE_TIME_FORMAT f; text format 


} 


} 
Property 


time.ds 


time.f 


TIME methods 
JTO SET 


INT to_set (INT format, 


the currently set date and time for an instance, in days and seconds, stored 
as two Loncs. It is manipulated by those methods adding or subtracting 
seconds, days, months and years. It should not be changed by any 
subclass. 


the currently set textual format and the date and time separator characters 
that will be used when requesting the time and date as a zero terminated 
text string. It should not be directly accessed by any subclass. 


Set time 


VOID *pdata); 


time from a variety of representations of the time. The representation is 


pdata Is the address of a uLonc containing the system time. The system time 
is the number of seconds since 00:00:00, January Ist 1970. 


pdata is the address of a p_pate structure. See the PLIB manual for a 
description of the p_pate structure. 


pdata is the address of a p_paysec structure. See the PLIB manual for a 
description of the p_payssc structure. 


uses p_date to set the time to the current system time (pdata is ignored). 


Set time's current date and 
specified by format as follows: 
SET_TIME_SECONDS 
SET_TIME_DATE 
SET_TIME_DAYSEC 
SET_TIME_NOW 
SET_TIME_DATESTR 


pdata is the address of a string representation of the date (the time of day is 
not changed). The date string should be in numeric form and include the 
day, month and year number in the current order (as defined in the format, 
set using the To_sET_FoRMaT method) and delimited by the current date 
delimiter or any punctuation character. If the year field has two digits and is 
greater than or equal to 70, it is added to 1900; otherwise it is added to 2000. 
If a date is set successfully, the method returns the number of characters 
processed. 


OLIB REFERENCE 


SET_TIME_TIMESTR pdata Is the address of a string representation of the time of day (the date is 
not changed). The time string should contain either two or three fields, 
separated by the current time delimiter or any punctuation character. If there 
are two fields, they are assumed to be hours and minutes and the seconds are 
set to zero. If there is a trailing string which matches the am/pm string 
returned by To_cET_syspar, this is processed with appropriate effect. If a 
time is set successfully the method returns the number of characters 
processed. 


If successful (i.e. *pdata defined a legal time), the method returns either zero or, if appropriate, the 
positive number of characters processed. Otherwise the current time is not modified and the method 
returns one of the negative error numbers &_GEN_ARG Or E_GEN_FAIL. 


J TO SENSE Sense time 


INT to_sense(INT format, VOID *pdata); 


Write a partial or complete representation of the current time to *pdata, where the representation depends 
on format as follows: 


SENSE_TIME_SECONDS pdata is the address of a utonc to take the current time in system time 
format. 

SENSE_TIME_DATE pdata is the address of a p_pate structure to take the current time. 

SENSE_TIME_DAYSEC pdata is the address of a p_payszc structure to take the current time. 

SENSE_TIME_STRING pdata is the address of a buffer, which must be at least LN_TIME_DATE_STR 


bytes in length, to receive a textual representation of the date and time as a 
zero terminated string. The conversion is controlled by the current format, as 
last set by the to_set_format method. 


SENSE_TIME_DATESTR pdata is the address of a buffer, which must be at least LN_TIME_DATE_STR 
bytes in length, to take a textual representation of the date as a zero 
terminated string. 


SENSE_TIME_TIMESTR pdata is the address of a buffer, which must be at least LN_TIME_DATE_STR 
bytes in length, to take a textual representation of the time of day as a zero 
terminated string. 


See the to_get_sysdat method for further information on the size limits for various components of the 
date and time strings. 


Returns zero if the time was written successfully to *pdata, or one of the following negative error 
numbers: 


E_GEN_UNDER if the current time is too early for the requested format 


E_GEN_OVER if the current time is too late for the requested format 


J TO_ADD_SECS Add seconds 


INT to_add_secs (INT lsw, INT msw); 
INT to_add_secs (LONG nsecs); (conceptual) 


Add the signed quantity nsecs to the current time of day. The Lone nsecs is actually passed in the 
message as two INT parameters, 1sw (least significant word) and msw (most significant word). 


If the number of seconds added is such as to cross the end (or start, if nsecs is negative) of a day the 
number of days is adjusted accordingly. 


The new time of day is set modulo 86400 (the number of seconds in a day). 


Returns zero if the adjusted time and date is legal. Otherwise the current time and date are not changed 
and the method returns one of the following negative error numbers; 


E_GEN_UNDER if nsecs 1s negative and it would take the time earlier than January Ist 1900 


E_GEN_OVER if nsecs is positive and it would take the time later than the latest date which 
can be supported (about 11.7 million years AD) 


3 THE TIME CLASS 


For example, to add one minute to the current time: 


INT AddMinute(PR_TIME *self) 
{ 
return (p_send4 (self,O_TO_ADD_SECS, 60,0) ); 
} 


JTO_ADD DAYS Add days 


INT to_add_days (INT lsw, INT msw); 
INT to_add_days(LONG ndays); (conceptual) 


Add the signed quantity ndays to the current date. The current time of day is unaffected. The Lone ndays 
is actually passed in the message as two INT parameters, 1sw (least significant word) and msw (most 
significant word). 


Returns zero if the new date is legal. Otherwise the current date is not changed and the method returns 
one of the following negative error numbers; 


E_GEN_UNDER if ndays 1s negative and it would take the time earlier than January Ist 1900 


E_GEN_OVER if ndays is positive and it would take the time later than the latest date which 
can be supported (about 11.7 million years AD) 


For example: 
INT AddDays(PR_TIME *self, LONG ndays) 


{ 


INT lsw,msw; 


lsw=ndayséOxffff; 

msw=ndays>>16; 

return (p_send4 (self, O_TO_ADD_DAYS,1sw,msw) ) ; 
} 


JTO_ADD MONTHS Add months 


INT to_add_months (INT nmonths) ; 
Add the signed quantity nmonths to the current date. The current time of day is unaffected. 


Returns zero if the new date is legal. Otherwise the current date is not changed and the method returns 
one of the following negative error numbers; 


E_GEN_UNDER if nmonths is negative and it would take the time earlier than January Ist 
1900 
E_GEN_OVER if nmonths is positive and it would take the time later than the latest date 


which can be supported (about 11.7 million years AD). 


JTO_ADD YEARS Add years 


INT to_add_years (INT nyears); 
Add the signed quantity nyears to the current date. The current time of day is unaffected. 


Returns zero if the new date is legal. Otherwise the current date is not changed and the method returns 
one of the following negative error numbers; 


E_GEN_UNDER if nyears is negative and it would take the time earlier than January Ist 
1900 
E_GEN_OVER if nyears is positive and it would take the time later than the latest date 


which can be supported (about 11.7 million years AD) 


OLIB REFERENCE 


J TO_SENSE_ FORMAT 


VOID to_sense_format (SE_TIME_FORMAT *pf); 


Sense format 


Write the current format data to «pr. See the to_set_format method for an explanation of the fields in the 
SE_TIME_FORMAT Struct. 


It is typically used to obtain the current settings before changing a format field by means of the 
to_set_format method. 


J TO_SET_FORMAT 


VOID to_set_format (SE_TIME_FORMAT *pf, UINT mask) ; 


Set format 


Stores format parameters which are subsequently used when converting to and from textual 
representations of time. 


If pf is NuLL, the method uses system services to set as many components of the format as possible. It does 


this by sending itself a ro_czET_syspaT message with a format of Ty_TIME_FoRmat. In this case the value 
of mask is ignored. 


Otherwise, pf should point to an sz_TIME_FORMAT struct. 


The values of pf->dsep and pf->tsep should be the new character codes for the required date separator 
and time separator. Either (or both) may be nu, in which case the corresponding existing separator is 
not changed. 


The value of pf->flags, together with mask, sets or clears a combination of format flags. Both should 
contain an ored combination of the following bit flags, where the bits set in mask determine which items 
should be changed, and the corresponding bit in pf->£1ags (set or clear) determines the new value. To 
change all bits as specified by pf->f1ags, mask should be set to oxf+. The bit flags have the following 


meanings 1n p£->flags: 


PR_TIME_DDMMYY if present, the date will be written in day-month-year order (European style) 

PR_TIME_MMDDYY if present, the date will be written in month-day-year order (USA style) 

PR_TIME_YYMMDD if present, the date will be written in year-month-day order (Japanese style - 
also good for sorting) 

PR_TIME_NO_DAY if present, the day is omitted 

PR_TIME_NO_MONTH if present, the month is omitted 

PR_TIME_NO_YEAR if present, the year is omitted 

PR_TIME_MONTH_NAME if present, the month is shown as a name rather than a number 

PR_TIME_SUFF1IX_NAME if present, a suffix is added to the day number (eg Ist, 2nd, 3rd). 

PR_TIME_DAY_NAME if set, the day name is written (with a trailing comma) before the date 

PR_TIME_NO_CENTURY if present, the year is displayed in two digits without the century 

PR_TIME_NO_SECS if present, the time is displayed without a seconds field 

PR_TIME_AMPM if present, the time is written in the 12 hour system with a trailing "am" or 


"pm" (preferred in the USA), otherwise, it is written using the 24 hour 
system 


If setting pR_TIME_DDMMYY, PR_TIME_MMDDYY Of PR_TIME_YYMMDD, no more than one of them should be 
present in pf->flags and all three should be set in mask. (PR_TIME_DDMMyy Is zero so, strictly speaking, it 
does not need to be set in mask. Setting the other two in mask and not including any of them in pf->flags 
has the same effect as including pR_timz_ppmmyvy. For this reason, the constant pR_TIME_DATE_ORDER iS 
defined as a combination of pR_TIME_mMmppyy and PR_TIME_YYMMDD.) 


3 THE TIME CLASS 


The following example first sets default format data from the current system settings. It then modifies the 
date separator character to a colon (:) and adjusts the time format to include a display of seconds and an 
am/pm indicator: 


VOID TimeSetup(PR_TIME *self) 


{ 
UINT mask; 
SE_TIME_FORMAT f; 


p_send4 (self,O_TO_SET_FORMAT,NULL,0); /* set defaults */ 

f.dsep=':'; 

f.tsep=NULL; /* don't change this */ 

£.flags=PR_TIME_AMPM; 

mask=PR_TIME_NOSECS | PR_TIME_AMPM; 

p_send4 (self,O_TO_SET_FORMAT, &£,mask); /* clear NOSECS bit and set AMPM bit */ 
} 


J TO_GET SYSDAT Get system date and time information 


INT to_get_sysdat (UBYTE *buf, UINT type, UINT n); 


Unless type is TY_TIME_FORMAT, Write a time-related name, as a zero terminated string, to *buf and return 
the length of the string copied. 


The caller is responsible for ensuring that the buffer is of sufficient size to take the appropriate string. 
Regardless of the language, each string is guaranteed not to exceed the following lengths: 


e aday name will not exceed LN_TIME_Day_Name (14) characters 
e amonth name will not exceed LN_TIME_MoNTH_NaME (14) characters 


e any format of date string (built from a combination of items, including those written by this 
method) will not exceed LN_TIME_DATE_sTR (48) characters 


e any format of time string (built from a combination of items, including those written by this 
method) will not exceed LN_TIME_TIME_sTR (12) characters 


The name type is selected by the value of type, as follows: 


TY_TIME_DAY selects the name of the day corresponding to the day number, n (modulo 7) 
TY_TIME_MONTH selects the name of the month where n is the month number (modulo 12) 
TY_TIME_SUFFIX selects the day suffix name where n is the day in month number (modulo 31) 
TY_TIME_AMPM selects the am/pm string where n is 0 for am and 1 for pm (modulo 2) 


Although this method may be of use to a client, it is primarily present for internal use when formatting 
date and time strings. 


It uses PLIB and operating system services to get the names. A subclass can replace this method if 
alternative names are required. 


If type iS Ty_TIME_FoRmaT, the method writes a system-supplied sz_TIME_FoRMAT structure to *buf (with 
no terminating zero) and returns sizeof (SE_TIME_FORMAT) . 


The tTy_TIMz_Format type is used by To_sET_rormat when the address of the format data is nuLL. 
Although this type does not really fit with the others, its inclusion here localises the system-dependent 
portion of the time class to this method. 


CHAPTER 4 


THE SGBUF SEGMENTED BUFFER CLASS 


nbytes 


cur 


destroy 
b_init 
b_point 
b_insert 


b_delete 


b_compress 
b_ count 


b_backpoint 


s 
s 
s 
Ss 
sb_extract 
s 
s 
Ss 
s 


b_allocseg 


Conceptually, the data held in an instance of the scBur class can be regarded as being stored in a variable 
sized linear buffer. 


The data is actually stored in memory in a linked list of allocated heap cells of equal size. Insertions and 
deletions may allocate or free cells and will, in general, cause data to be transferred from one cell to 
another. All cells will generally be at least 50% full. 


Since the segmentation of the data is largely hidden from a user of scBur, the data should not be accessed 
other than via the supplied methods. 


Precursors 


An understanding of the scBur class will be aided by a knowledge of: 
e the PLIB memory allocator functions. 


e =the p_enter and p_leave error handling services. 


OLIB REFERENCE 


Class definition 


The scpur class subclasses root and is defined in the sub-category file varray.cl (with generated header 
file varray.g). 


CLASS sgbuf root 
Segmented buffer object 


{ 
REPLACE destroy 


ADD sb_init Initialise with segment length 

ADD sb_point Get the address from a position 

ADD sb_insert Insert at specified position 

ADD sb_delete Delete at specified position 

ADD sb_extract Extract from specified position 

ADD sb_compress Compress buffer 

ADD sb_count Return no. of bytes in buffer 

ADD sb_backpoint Get the address before a position 
ADD sb_allocseg Allocate memory segments as required 
TYPES 


typedef struct 


{ Segment header 
P_QUE q; Links to neighbouring segments 
UWORD len; Number of bytes currently in segment 


} PR_SGBUF_HD; 
typedef struct 
{ 
PR_SGBUF_HD *seg; Current segment, or NULL 
UWORD base; Character position of start of current segment 
UWORD ofs; Current offset into segment 
} PR_SGBUF_SBO; 
} 


PROPERTY 
{ 
PR_SGBUF_HD hd; Head of queue 
UWORD nbytes; Total number of bytes in buffer 
PR_SGBUF_SBO cur; Current position for efficient positioning 
} 
} 
Property 
sgbuf.hd The head of the linked list of segments containing the data. Also contains 
the length of each allocated segment. 
sgbuf.nbytes The total number of bytes of content. 
sgbuf.cur The last accessed position as the current segment buffer, the character 


position of the first character in that buffer and the character offset within 
the buffer. This is used internally for efficient positioning when scanning 
sequentially. 


SGBUF methods 
J DESTROY Destroy 


VOID destroy (VOID) ; 


Delete the content, freeing all of the allocated segments, and then supersend the pEstrRoy message. 


JSB_INIT Initialise 


VOID sb_init (UINT len); 


Initialise the segment queue and set the required length of a segment by setting sgbuf.hd.1len tO len. 
Note that this is the length to be made available for data. The amount of memory allocated for a segment 
will actually be sgbuf.hd.1en plus the length of the header (i.e. the length of pR_scBuF_HD). 


The choice of the value of 1en is a compromise that depends on the nature of the data that is to be stored. 


4-2 


4 THE SGBUF SEGMENTED BUFFER CLASS 


A small value reduces the potentially wasted space within each segment (at worst a segment may be only 
half full) but increases the likelihood that data will need to be moved from one segment to another during 
insertion or deletion. A small segment size is therefore more appropriate when the data is not expected to 
change very frequently. 


A larger value of 1en is more suitable for situations where the data will frequently change, but may result 
in more potentially wasted space, particularly if the maximum expected content is small. In addition, 
when data does move from segment to segment, the larger the segment, the more data is likely to be 
moved. 


As a rough guideline, it may be noted that all text editing applications on the Series 3 use a segment size 
of 64 bytes. If necessary in a particular case, an optimum value can be found empirically by timing a 
typical operation with a range of different segment sizes. 


When a sequence of fixed length items is to be stored, insertion, deletion and access to items will be much 
more efficient if the segment size is an exact multiple of the item size. 


No segments are allocated until data is inserted. 


J SB POINT Sense data by position 
UINT sb_point (VOID **pbuf, UINT pos); 
Write, to *pbuf, the address of the data at position pos. 


Calls p_panic (P_PANIC_P_SGBUF_1) If pos is outside the range of the segmented buffer content. 


Updates its internal record of the current position. 
Returns the number of contiguous bytes of data available at *pbut. 


Does not write to *pbuf and returns zero if there is no data in the segmented buffer. 


SB_INSERT Insert 


VOID sb_insert (UINT pos, VOID *pbuf, UINT len) 


Create a gap of size 1en bytes at position pos in the segmented buffer and then inserts the 1en bytes of 
data from pbuf. 


The inserted data may span more than one segment, with more segments being allocated as necessary. If 
opening the gap causes data to overflow from the segment containing the insertion point, then this data 
will be inserted into the last of any newly created segments and/or any immediately following segment 
that previously existed. 


The allocation of segments is performed by sending an sB_ALLOCSEG message. 
The value of sgbuf.nbytes is adjusted to indicate the new number of bytes in the segmented buffer. 


Calls p_panic (P_PANIC_P_SGBUF_1) if position pos is outside the range of the segmented buffer. 


Inserts nothing and calls p_leave (E_GEN_NoMEMoRY) if it fails to allocate any extra segments required. 


JSB_ DELETE Delete 


VOID sb_delete(UINT pos, UINT len); 


Delete 1en bytes from position pos. This may involve copying data between segments. If a segment 
becomes empty then it will be freed. 


The value of sgbuf.nbytes is adjusted to indicate the new number of bytes in the segmented buffer. 


Calls p_panic(P_PANIC_P_SGBUF_1) if position pos is outside the range of the segmented buffer. Calls 
p_panic (P_PANIC_P_SGBUF_2) if position pos+1len 1s outside the range of the segmented buffer. 


OLIB REFERENCE 


JSB_EXTRACT Exract 


VOID sb_extract (UINT pos, VOID *buf, UINT len); 


Copy len bytes of data from position pos into the buffer at bur. If necessary, data is copied from more 
than one segment. The buffer is assumed to be large enough to hold 1en bytes of data. 


Calls p_panic (P_PANIC_P_SGBUF_1) if position pos is outside the range of the segmented buffer. 


J SB COMPRESS Compress 


VOID sb_compress (VOID) ; 


Compress the segmented buffer by moving data to fill the early segments. Any segments that are emptied 
by this process will be freed. 


J SB COUNT Count characters 


UINT sb_count (VOID) ; 


Return the number of bytes currently held within the segmented buffer. 


J SB _BACKPOINT Sense previous characters 


UINT sb_backpoint (VOID **pbuf, UINT pos); 


Write, to *pbuf, the address of the byte of data that is the lowest in memory and contiguous with the byte 
at position pos-1. In general, *pbuf will contain the address of the first byte of data in the segment 
containing the byte at position pos. If position pos is at the beginning of a data segment, *pbuf contains 
the address of the first byte of data in the previous data segment. 


Returns the number of bytes between the position corresponding to *pbuf and position pos. If the return 
value is n, data is only guaranteed to be valid at addresses of *pbuf to *pbuf+n-1 inclusive. 


If pos is zero nothing is written to *pbuf and the method returns zero. This is the only position for which 
the return value is zero. 


Calls p_panic(P_PANIC_P_SGBUF_1) if position pos is outside the range of the segmented buffer. This 
method may be regarded as the complement of sb_point and would typically be used when searching 
backwards through the content. 


SB_ALLOCSEG Allocate segments 


INT sb_allocseg(PR_SGBUF_HD *pseg, UINT nseg); 


Allocate a chain of nseg empty segments and insert the chain after the segment at *pseg. Each allocated 
segment is initialised to be empty by setting the 1en field of the segment header to zero. The amount of 
memory required for each segment is sgbuf.hd.1len plus the length of the segment header (i.e. the length 
of PR_SGBUF_HD). 


This method is used internally and is not intended to be called by a user of the scBur class. 


Does not allocate any segments and calls p_1leave (E_GEN_NOMEMoRY) if there is not enough memory to 
allocate all nseg segments. 


CHAPTER 5 


VARIABLE ARRAY CLASSES 


The classes described in this chapter implement arrays of a variable number of records, in which records 
are referenced by number. The first record is record zero and the last record is record n-1, where n is the 
total number of records in the array. Depending on the particular class, records may be of fixed or variable 
length. 


Unlike static C arrays, the space for the array is dynamically allocated from the heap. This means that 
adding a record to an array can fail owing to a failure to allocate additional memory. For some subclasses, 
it is possible to pre-set the capacity; this facility may be used when the required capacity is known in 
advance in order to avoid out of memory failures. 


Extending the capacity of an array generally involves either allocating additional heap cells or growing a 
heap cell using p_realloc. This is always done in such a way that the original handle to the object does 
not change. 


Precursors 

An understanding of the variable array classes will be aided by a knowledge of: 
e the PLIB memory allocator functions 
e =the p_enter and p_leave error handling services 


Class diagram 


om 
ae 


i varoot / 


Ban 


Z vaflat / Z sgbuf / 
~ ns) oe + ) 
L as 20 aes 

¢ vaxvars / re 
- ) 
Se tees eae 
¢ vaxvar / 
= ) 
Lae 


OLIB REFERENCE 


Usage summary 


varootT and vaFrrx are abstract classes. varoot defines a relatively large number of deferred methods in 
order to promote polymorphism between the directly usable classes. 


The vastr class is used to create arrays of variable length text records, stored as zero terminated strings. 
The storage overhead per string is only one byte, so it is particularly suitable for storing short strings, of 
up to, say, several tens of bytes, or for strings with a wide variation in size (such as file names, which can 
be any length up to 128 bytes, but are usually much shorter). Since the whole array is stored in a single 
allocated cell, the vastr class is most suitable for arrays that contain: 


e asmall number of records 


¢ amoderately large, but fixed maximum, number of records (for which the maximum capacity can 
be allocated in advance) 


Because of its suitability for storing file names, the vastr class is used, for example, to store directory 
listings. In general, however, the vastr class is not particularly suitable for arrays which can dynamically 
grow to a very large size. The resulting repeated calls to p_realloc are likely to cause heap fragmentation 
and seriously reduce the effective use of memory. 


The vartat class is used to create arrays of fixed length records, where the whole array is stored in a 
single allocated cell. The preferred usage is as for the vastr class. 


The vassc class is used to create arrays of fixed length records where the array is segmented into a 
number of equal sized blocks. It is suitable for large, dynamically changing arrays. Its disadvantage is that 
it takes longer to locate a random record by record number because it has to count through the segments, 
although sequential access to the records is reasonably efficient. 


The vaxvar class is used to create arrays of variable length records which, unlike those of the vastr class, 
may contain arbitrary data. It uses an index which is stored in a single allocated cell and thus, like vastR 
and vaFr.art, 1s best suited to arrays containing either a small number of records or a larger but fixed 
number of records. Since each record is stored in a separate allocated cell, it is more suited to the storage 
of longer records, where the increased overhead per record is less significant. 


The vaxvars class (which has a segmented index) should be used instead of vaxvar when there is a 
possibility of growth to a large number of records. 


Record pointers 


Many of the variable array methods take a record pointer prec as a parameter. The va_prec method, 
defined as a deferred method by varoot, and which converts a record number into a prec record pointer, 
assumes that each record is stored in such a way that it is possible to provide a record pointer that is 
equivalent to an external pointer. In most subclasses this assumption is valid. Subclasses that are, because 
of their internal structure, unable to provide a va_prec method may still inherit usefully from varoot, but 
should replace all inherited methods which rely on va_prec (va_findisq, va_search and va_compare). 


In most, but not all, subclasses of varooT, prec is the address of the record data. A more general 
interpretation of prec is that it is a handle to a record in the array. In a variable length record array 
subclass, for example, prec might be the address of a string descriptor which contains the address and 
length of a buffer containing the record. 


In contrast with va_prec, the va_pbuf method converts a record number into a pointer that is guaranteed 
to point to the record data. Although in most cases (see, for example, varLat and vastTR) va_prec and 
va_pbuf return identical pointers, they would return different addresses in the case mentioned in the 
previous paragraph (see also the vaxvar and vaxvars classes). 


In general, there is no guarantee that any method will not cause the data of one or more records to move 
in memory. An application should therefore always access records by record number and should not store 
the pointers supplied by either the va_prec or the va_pbuf method. 


When scanning records, the user should not rely on the assumption of contiguous storage to scan through 
the records. Although that is true for some types of variable array, it is certainly not true in general. 


None of the supplied methods ever refers to more than two record pointers at any one time. This means 
that the data of a variable array may be stored in a separate segment and only the last two accessed records 
need to be copied into the local data space. 


5 VARIABLE ARRAY CLASSES 


VAROOT 


VAROOT 


destroy 
va_count 
va_delete 
va_sort 


va_key 


va_findisg 


va_insertisq 


va_append 
va_insert 


va_search 


va_compare 


va_reset 


va_test 


va_replace 


va_copy 
va_reclen 
va_swap 


va_init 


va_insertm 


va_prec 


va_pbuf 


va_capacity 


va_compress 


va_deletem 


The varoot class is an abstract class which must be subclassed to provide a usable variable array class. 


This abstract class does not assume that the records are of fixed length. It is designed so that it may be 
subclassed by classes in which the records are of either fixed or variable length. 


The assumption that prec is a pointer to the record itself is made by only one method in this class - 
va_test. If this assumption is not true for a particular subclass, that subclass should replace va_test with 
a more appropriate method. 


Class definition 


Defined in sub-category file varray.cl (generated header file varray.g). 


CLASS 


varoot 


root 


The root class for variable arrays. 


{ 


REPLACE destroy 


prppprrrrrrere 
GDUUOTGTV00 00D 


DEFER 
DEFER 
DEFER 
DEFER 
DEFER 
DEFER 
DEFER 
DEFER 
DEFER 
DEFER 


DD va_count 
D va_delete 

D va_sort 

D va_key 

D va_findisq 

D va_insertisgq 
D va_append 

D va_insert 

D va_search 

D va_compare 

D va_reset 

D va_test 

DD va_replace 


va_copy 
va_reclen 
va_swap 
va_init 
va_deletem 
va_insertm 
va_prec 
va_pbuf 
va_capacity 
va_compress 


CONSTANTS 


{ 


VA_ROOT_DUPLICATE 


VA_ROOT_FLG_FOLD 
VA_ROOT_FLG_DESC 


i 


Send itself a va_reset message first 
Return record count 

Delete a record 

Sort array 

Set key parameters 

Find a record in an ordered array 
Insert a record in sequence 

Append after last record 

Insert before a record 

Search for a match 

Compare two records 

Reset to zero records and capacity 
Compare a record with a test record 
Replace a record 

Copy a record 

Return record length 

Swap two records 

Initialise an array 

Delete a record range 

Insert a record sequence 

Return the address of record n 
Point at the buffer data - usually same as prec 
Set record capacity 

Compress memory usage 


1 
Ox01 
0x02 


OLIB REFERENCE 


TYPES 


{ 
typedef struct 
{ 


UBYTE ofs; offset for comparison 

UBYTE len; length for bcmp (scmp if zero) 
UBYTE fold; fold case if set 

UBYTE desc; reverse compare result if set 


} PR_VAROOT_KEY; 
} 


PROPERTY 
{ 
UWORD nrec; number of records in the array 
PR_VAROOT_KEY key; defines key for sort etc 
} 
} 


Property 
varoot.nrec Holds the current record count. Each subclass is expected to maintain this 
field. 
varoot .key Holds the current sort key. See the va_key method for a description of the 


PR_VAROOT_KEYy Structure fields. 


VAROOT methods 
& DESTROY Destroy 


VOID destroy (VOID) 


Destroy the array by sending itself a va_RESET message before supersending a DESTROY message. 


& VA_COUNT Count records 


UINT va_count (VOID) 


Return the number of records in the array from varoot .nrec. 


VA_APPEND Append a record 


VOID va_append(VOID *prec) 
Append the record pointed to by prec to the end of the array. 


This is done by sending itself a va_INSERT message to insert the record at a position given by 


varoot.nrec. 


It will call p_1eave if the va_insert method for that particular subclass calls p_leave, for example, if it 
fails to allocate any necessary additional memory. 


VA_INSERT Insert a record 


VOID va_insert (UINT recno, VOID *prec) ; 
Insert the record pointed to by prec before record recno. 


This is done by sending itself a va_INSERTM message with recno, prec and 1 (i.e. one record) as 
parameters. 


It will call p_teave if the va_insertm method for that particular subclass calls p_1eave, for example, if it 
fails to allocate any necessary additional memory. 


5 VARIABLE ARRAY CLASSES 


& VA_DELETE Delete a record 


VOID va_delete(UINT recno); 


Delete record recno from the array by sending itself a va_DELETEM message with recno and 1 (i.e. one 
record) as parameters. 


& VA_KEY Set key for comparisons 


VOID va_key(UINT offset, UINT length, UINT flags); 


Define the parameters which are used by va_test and, indirectly, by va_compare, va_sort, va_findisq 
and va_insertisq. 


The parameters are: 


offset - sets the offset (0 to 127 inclusive) into the record at which the comparison begins. The value 
is copied into varoot.key.ofs. 


length - if non-zero, this sets the length of the comparison (1 to 127 inclusive) and, if zero, sets the 
comparison to be between two zero terminated strings. The value is copied into varoot.key.len. 


flags - any combination of the two flags va_RooT_FLG_FOLD and va_RooT_FLG_DEsc. If the 
VA_ROOT_FLG_FOLD flag is set, the comparison is case independent. If the va_Root_FLG_pEsc flag 
is set, the result of the comparison is reversed, to give descending rather than ascending order. 
The values of flags&VA_ROOT_FLG_FOLD and flags&VA_ROOT_FLG_DESC are copied into 
varoot .key.fold and varoot .key.desc respectively. 


The default settings are offset = 0, length = 0, flags = 0, giving ascending order, case-dependent 
string comparisons, from offset zero in the record buffer. 


See the va_test method for further discussion of the va_key parameters. 


& VA_TEST Compare two records by pointer 


INT va_test (VOID *precl, VOID *prec2); 


Compare the record pointed to by prec2 with the record at preci on the assumption that the records 
contain text. The basis for the comparison is subject to the contents of varoot .key, as set by the method 
va_key, aS follows: 


if varoot .key.len==0 it uses 
p_scmp df varoot.key.fold is FALSE), or 
p_scmpi af varoot.key.fold is TRUE). 


if varoot .key.len>0 it uses 
p_bemp (if varoot .key. fold iS FALSE), OF 
p_bcempi af varoot.key.fold is TRUE). 


The default is to use p_scmp. 


Returns the logical equivalent of (*preci-*prec2) - that is, zero if the two records are equal, negative if 
*prec1 is before (less than) *prec2, positive if after. If key. desc is TRUE this result is reversed. 


This method is used directly by va_findisg, va_search and va_compare. It is used indirectly by va_sort 
and va_insertisq. 


Subclasses which are unable to provide va_prec, or in which va_prec does not return a pointer to the 
data to be compared, must replace this method. 


& VA_COMPARE Compare two records by number 


INT va_compare(UINT nl, UINT n2); 


Compare record ni with record n2 by sending itself va_pREc messages to get pointers to the records and 
then sending itself a va_tEst message to perform the comparison that determines the return value. 


Returns the logical equivalent of n1-n2, that is, zero if the two records are equal, a negative value if record 
n1 is less than (before) record n2 or a positive value if record ni is greater than (after) record n2. Note the 
effect of the va_RooT_FLG_FOLD and va_ROoT_FLG_pDEsc flags. 


This method is used directly by va_sort. 


Subclasses which are unable to provide va_prec must replace this method. 


OLIB REFERENCE 


VA_SORT Sort 


VOID va_sort (VOID) 
Sort the records of the array. 


The sort uses the quicksort algorithm. This is an efficient exchange sort using va_compare and the 
deferred va_swap respectively to compare and to exchange two records. 


Subclasses which are unable to implement va_swap efficiently should either not support va_swap or 
subclass va_sort to sort by some other means. Not supporting va_swap does not mean that the array may 
never be ordered; ordered arrays can still be constructed using va_insertisq. 


The method uses va_compare (and hence va_test) to compare two records. The sort key is determined by 
va_test, as qualified by the last use of va_key. If the flexibility afforded by va_key is insufficient (for 
example, to sort on multiple keys) va_test may be replaced. 


Note that the vastr class does not support this method. In such a case the array may be built in order, by 
using the va_insertisq method. 


& VA_FINDISQ Find (binary chop) 


INT va_findisq(VOID *pkey, VOID *pmid) ; 

Find a record in an ordered array, using the binary search algorithm. 

The record to be found is specified by pkey which is typically a record pointer (prec). 

Returns zero if an exact record match is found, with the record number of the matching record in *pmia. 


If there is no matching record, *pmid contains the record number of one of the two records adjacent to the 
key and va_findisg returns the logical equivalent of *pkey-*pmid, that is, a negative value if *pkey is 
less than (before) the existing record with record number *pmia, or a positive value if *pkey is greater 
than (after) record number *pmid. 


The method uses va_test, passing pkey as the first parameter; the second is a pointer to one of the 
records in the ordered variable array and is determined by the binary search algorithm itself as it works 
through its search. 


The result will be unpredictable if the array is not ordered. (An array may be ordered either by applying 
va_sort or by using va_insertisgq to build the array.) 


VA_INSERTISQ Insert in sequence 


INT va_insertisq(VOID *prec,UWORD *precno) ; 


Insert the record pointed to by prec in sequence into an ordered array using va_findisg to locate the 
insertion point. 


If there is no matching record, it sends itself a va_INnsERTm message. If the insertion is successful, the 
record number of the inserted record is written to *precno and va_insertisq returns zero. 


The record is not inserted if there is already a matching record in the array (that is, if va_compare would 
return zero). In this case va_insertisq returms VA_ROOT_DUPLICATE (which is a positive number) and 
writes the matching record number to *precno. 


Since it sends a vA_INSERTM message, it is quite possible for the insert to fail with out of memory and call 


p_leave. 


© VA_SEARCH Search 


INT va_search(VOID *pkey) ; 
Sequentially search for a record which exactly matches that specified by pkey. 


The search is performed by sending a va_tEsT message to compare each record in the array (obtained by 
use Of va_prec) with the data pointed to by pkey, which is assumed to be a record pointer. 


Returns the record number if found (+ve number or zero) or E_GEN_FAIL if not. 


5-6 


5 VARIABLE ARRAY CLASSES 


& VA_RESET Reset 


VOID va_reset (VOID) 


Reset the array to its state just after its creation (and, if appropriate, a va_init). Following a va_reset the 
array contains no records and has no record capacity. 


The method is implemented by sending itself a va_bzELETEM message to delete varoot .nrec records, 
starting from record 0. This is followed by a va_compress message to discard all record capacity. 


The method has two principal uses: 


e It provides the client with a concise and efficient way to delete all records in the array and, at the 
same time, to zero the capacity. 


e itis used by the destroy method to remove all allocated cells, other than the object instance cell, 
prior to the freeing of the instance itself. 


This implementation assumes that the va_compress method always frees all additional allocated cells 
when an array contains no records. (This assumption is true for all OLIB array classes.) 


VA_REPLACE Replace a record 


VOID va_replace(UINT recno, VOID *prec); 
Replace record number recno with the record pointed to by prec. 


The method is implemented by using a va_DELETE message to delete record recno, followed by a 
VA_INSERT message to insert prec at position recno. 


The implementation of this method is aimed at variable length record subclasses; fixed length record 
subclasses can replace it by a more efficient method (for example, by simply overwriting the record data). 


Deferred VAROOT methods 
& VA_COPY Copy a record 


UINT va_copy(UINT recno, VOID *prec); 
A deferred method for copying the contents of record recno tO prec. 
Returns the length copied. 


Not used by any methods in this class but deferred, to promote polymorphic subclasses. 


& VA_RECLEN Get record length 
UINT va_reclen(UINT recno); 
A deferred method for returning the record length of record recno. 


Not used by any methods in this class but deferred, to promote polymorphic subclasses. 


VA_SWAP Swap two records 


VOID va_swap(UINT nl, UINT n2); 
A deferred method for swapping the contents of record n1 with those of record n2. 


Used by va_sort. 


OLIB REFERENCE 


VA_INIT Initialise 


VOID va_init(...) 
A deferred method for initialising the property of the newly created array. 


No record capacity is allocated until the first record insertion or va_capacity message. All subclasses 
should ensure that this is the case. However, the method may still fail, calling p_1eave (&_GEN_NOMEMORY) 
if the subclass has other memory requirements (vasec, for example, creates a component object). 


The parameters depend upon the subclass. For example, a fixed length record subclass would require the 
record length as a parameter. 


Not used by any methods in this class but deferred, to promote polymorphic subclasses. 


VA_CAPACITY Set capacity 


VOID va_capacity(UINT nspc); 
A deferred method for setting the capacity of the internal storage. 


The interpretation of the parameter nspc is dependent on the subclass. For example, nspc might 
reasonably be the number of records in a fixed length record subclass, or it might be the total number of 
bytes of allocated storage in a variable length record subclass. 


It is not always possible to provide this method in a meaningful way and some subclasses are expected to 
dummy it. 


Not used by any methods in this class but deferred, to promote polymorphic subclasses. 


VA_COMPRESS Compress 


VOID va_compress (VOID) ; 


A deferred method for compressing the capacity of the array as much as is reasonable and sensible (this 
judgement is left to the subclass). 


The supplied destroy method assumes that va_compress frees all allocated cells used to hold records 
when there are no records in the array. If this is not true, the destroy method must be subclassed. 


The va_compress method is used directly by va_reset and indirectly by destroy. 


VA_DELETEM Delete sequence of records 
VOID va_deletem(UINT recno, UINT nrecs); 
A deferred method for deleting nrecs records, starting with record number recno. 


Used directly by va_delete and va_reset and indirectly by destroy. 


VA_INSERTM Insert sequence of records 
VOID va_insertm(UINT recno, VOID *prec, UINT nrecs) ; 
A deferred method for inserting a sequence of nrecs records, pointed to by prec, before record recno. 


If it fails to allocate enough memory to hold the new records it should allocate nothing and call p_leave 
since, typically, va_insert and va_append are void functions and va_insertisq returns an insertion 
indicator. 


Used directly by va_insert and indirectly by va_append and va_insertisq. 


5 VARIABLE ARRAY CLASSES 


VA_PREC Point to record 


VOID *va_prec(UINT recno); 
A deferred method for returning a pointer to record recno. 
See the introductory discussion of the varoot class for the meaning of a record pointer. 


Used directly by va_compare, va_findisg and va_search, and indirectly by va_insertisq and va_sort. 


VA_PBUF Point to record data 


VOID *va_pbuf (UINT recno); 
A deferred method for returning a pointer to the record data of record recno. 


Typically, it returns the same value as for va_prec. in some classes, however, the record pointer may not 
be the same as the record data pointer (this is true for the vaxvar and vaxvars classes) or the record may 
contain a header to the data. 


The va_pbuf method should always be used in preference to va_prec when a pointer to the data of the 
record is required. 


VAFIX 


VAROOT 


destroy va_replace 
va_count va_copy 
va_delete va_reclen 
va_sort va_swap 


va_key 


va_findisgq va_init 


va_insertisq va_deletem 
va_append va_insertm 
va_insert va_prec 
va_search va_pbuf 
va_compare va_capacity 
va_reset va_compress 


va_test 


The varrx class is an abstract class for fixed length record variable arrays. In addition to adding the 
record length rien to the property, it: 


e implements the deferred methods va_swap, va_copy and va_reclen. 
e replaces va_replace by a more efficient method. 


The methods are provided on the assumption that the record pointer prec is simply the address of the 
record (reasonable when records are of fixed length). 


OLIB REFERENCE 


Class definition 


Defined in sub-category file varray.cl (generated header file varray.g). 
CLASS vafix varoot 


Fixed length record variable arrays. 


{ 


REPLACE va_replace More efficient than varoot's 
REPLACE va_swap Uses p_bswap 
REPLACE va_copy Uses p_bcpy 
REPLACE va_reclen Returns property value 
PROPERTY 
{ 
UWORD rlen; Record length 
} 
} 
Property 
vafix.rlen the record length, set by a subclass va_init method. Each subclass is 


expected to set this field. 


VAFIX methods 
& VA_REPLACE Replace a record 


VOID va_replace(UINT recno, VOID *prec); 


Replace the specified record by sending itself a va_pREc message to convert recno into a record pointer 
and then using p_bcpy to overwrite that record with the record at prec. 


& VA_COPY Copy a record 


UINT va_copy(UINT recno, VOID *prec); 


Copy the specified record to prec by sending itself a va_pREc message to convert recno into a record 
pointer and then using p_bcpy to copy that record data from the array to prec. 


Returns the length copied. 


& VA_RECLEN Get record length 


UINT va_reclen (VOID) 


Return the record length, that is, the value of the vafix.rlen property field. 


& VA_SWAP Swap two records 


VOID va_swap (UINT n1,UINT n2) 


Swap the contents of record n1 with record n2 by sending two va_prEc messages to itself to turn n1 and n2 
into record pointers and then using p_bswap to swap the record contents. 


5 VARIABLE ARRAY CLASSES 


VASTR 


VAROOT 


key 


destroy va_replace va_copy 
va_count va_reclen 
va_delete va_init 
va_sort va_deletem 


va_key va_insertm 


va_findisgq Ad va_prec 


va_insertisq va_pbuf 
va_append i va_capacity 
va_insert va_compress 
va_search 

va_compare 

va_reset 


va_test 


The vastr class may be used to create arrays of variable length text records which are stored as zero 
terminated strings. Non-textual data may be used provided that the record data does not have any zero 
bytes in it. 


The whole array is stored in a single allocated cell. When a record is inserted into a full array, the single 
cell is reallocated to accommodate the additional record. Deletions do not automatically reduce the record 
capacity, but the capacity may be reduced manually using va_compress Of va_capacity. 


The record pointer prec points to a zero terminated string. Internally, the records are stored as a 
contiguous sequence of zero terminated strings. 


To locate a random record by record number, va_prec has to count through the records. However, the 
object remembers the last record accessed so that scanning the array sequentially from the first record is 
reasonably efficient. 


The vastr class is suitable for short arrays or for large arrays which have a known maximum capacity (in 
terms of the number of bytes required). It is not suitable for arrays which can dynamically grow to a large 
size because heap fragmentation can seriously reduce the effective use of the heap. 


The string array is especially suitable for strings that can vary greatly in size since the overhead per string 
(1 byte) is small. A typical use is for holding file name lists where each string can have a maximum 
length of p_rwames1zE (128) bytes but is usually less than 32 bytes long. 


OLIB REFERENCE 


Class definition 


Defined in sub-category file varray.cl (generated header file varray.g). 


CLASS 


vastr varoot 


Variable length text record variable arrays 


REPLACE va_copy 
REPLACE va_reclen 
REPLACE va_init 
REPLACE va_compress 
REPLACE va_capacity 
REPLACE va_deletem 
REPLACE va_insertm 
REPLACE va_prec 
REPLACE va_pbuf=vastr_va_prec 
PROPERTY 
{ 
UWORD size; current size of the array in bytes 
UWORD gran; re-alloc granularity 
UBYTE *base; base of the array 
UWORD len; offset to end of used data 
UWORD num; number of last record referenced 
UBYTE *pnum; pointer to record num 
} 
} 
Property 
vastr.size The current size of the allocated cell that contains the data. It should not 
be accessed by any subclass. 
vastr.gran The granularity, in bytes, used when expanding the allocated cell. It 


vastr.base 


vastr. 


vastr. 


vastr.pnum 


len 


num 


should not be accessed by any subclass. 
The allocated cell base. It should not be accessed by any subclass. 


The byte offset from vastr.base to the end of the data in the allocated 
cell. It should not be accessed by any subclass. 


The record number of last record referenced. It should not be accessed by 
any subclass. 


A pointer to the record specified by vastr.num. It should not be accessed 
by any subclass. 


VASTR methods 
© VA_INIT Initialise 


VOID va_init (UINT granularity) 


Initialise the array by setting vastr.gran to the passed granularity, which must be at least as large as 
the longest record to be inserted. No capacity is actually allocated until the first insertion. 


The granularity is significant when an insertion requires an increase in capacity; the increase is such that 
the capacity, in bytes, is made an exact multiple of the granularity. Making this value larger means that 
the array cell needs to be reallocated less frequently as a result of insertions, but more memory may be 
wasted in unused capacity. Any unused capacity may be recovered by sending a va_comPpRESS message 
when the building of an array is complete. 


5 VARIABLE ARRAY CLASSES 


VA_CAPACITY Set capacity 


VOID va_capacity(UINT nspc); 


Set the capacity of the allocated array cell by reallocating it to have exactly the capacity for nspc bytes (the 
granularity has no effect). 


The minimum space required is equal to the sum of the string lengths of all the records plus one byte per 
record for the terminating zero. 


Calls p_panic (P_PANIC_P_VASTR_2) If nspc is less than the current size of the array. 


& VA_COMPRESS Compress 


VOID va_compress (VOID) 


Compress the capacity of the array to that which will exactly contain the current records by sending itself 
a VA_CAPACITY message with vastr.len as the size. 


If there are no records in the array, the array cell is freed (as required by varoorT). 


& VA_DELETEM Delete a sequence of records 


VOID va_deletem(UINT num, UINT nrecs) ; 


Delete the sequence of nrecs records, starting at record number nun, and decrease the value of 
varoot.nrec by nrecs. 


The deletion is performed by simply copying all following records over the records to be deleted. No 
memory is freed. 


Calls p_panic(P_PANIC_P_VASTR_4) if num+nrecs 1s greater than the number of records in the array. 


VA_INSERTM Insert a sequence of records 


VOID va_insertm(UINT num, VOID *prec, UINT nrecs); 


Insert the sequence of nrecs records, pointed to by prec, before record number nun, and increase the value 
of varoot .nrec by nrecs. 


The valid range for num is from zero to the number of records inclusive. 


In the record sequence at prec, each subsequent string should immediately follow the zero terminator of 
the previous string. 


Calls p_panic(P_PANIC_P_VASTR_3) if num is greater than the number of records in the array. 


Inserts no records and calls p_leave (E_GEN_NOMEMoRY) if there is not enough memory available to hold all 
the additional records. 


& VA_RECLEN Get record length 


UINT va_reclen(UINT num); 


Return the record length of record number num. The returned length excludes the zero terminator. 


& VA_PREC Point to record 
VOID *va_prec(UINT num); 
Return the address of record number num. The pointer returned is to a zero terminated string. 


Calls p_panic(P_PANIC_P_VASTR_1) if num is greater than or equal to the number of records in the array. 


OLIB REFERENCE 


& VA_PBUF Point to record data 


VOID *va_pbuf (UINT num) 


AS VA_PREC. 


& VA_COPY Copy a record 


UINT va_copy(UINT num, VOID *prec); 


Copy the record specified by the parameter num to the location pointed to by the parameter prec; by 
sending itself a va_PREC message to convert recno into a record pointer and then using p_bcpy to copy 
that record data from the array to prec. 


Returns the length copied. 


VAFLAT 


VAROOT VAFIX 


destroy va_replace va_init 
va_count va_copy va_compress 
va_delete va_reclen va_deletem 


va_sort va_swap va_insertm 


va_key va_capacity 


va_findisgq ind va_prec 
va_insertisq va_pbuf 
va_append 

va_insert 

va_search 

va_compare 

va_reset 


va_test 


The variat class may be used to create arrays of fixed length records where the whole array is stored in a 
single allocated cell. When a record is inserted into a full array, the single cell is reallocated to 
accommodate the additional record. Deletions do not automatically reduce the record capacity but the 
capacity may be reduced manually using va_compress Or va_capacity. 


The vartat class is suitable for short arrays or for large arrays which have a known maximum capacity. It 
is not suitable for arrays which can dynamically grow to a large size because heap fragmentation can 
seriously reduce the effective use of heap memory. 


Class definition 
Defined in sub-category file varray.cl (generated header file varray.g). 


CLASS vaflat vafix 
Flat allocated (in a single cell) fixed length variable arrays 
{ 
REPLACE va_init 
REPLACE va_compress 
REPLACE va_deletem 
REPLACE va_insertm 
REPLACE va_capacity 
REPLACE va_prec 
REPLACE va_pbuf=vaflat_va_prec 


PROPERTY 
{ 
UWORD gran; granularity in records 
UWORD nspc; present record capacity 


UBYTE *base; start of variable array 
} 


5 VARIABLE ARRAY CLASSES 


Property 
vaflat.gran The granularity, in records, in which to allocate memory. It should not be 
accessed by any subclass. 
vaflat.nspe The number of fixed sized record slots allocated (greater than or equal to 
the number of records in the array). It should not be accessed by any 
subclass. 
vaflat.base The allocated space handle, i.e. the start of the variable array. It should 


not be accessed by any subclass. 


VAFLAT methods 
© VA_INIT Initialise 


VOID va_init (UINT reclen, UINT gran); 


Initialise the array by setting vafix.rlen from reclen and vaflat.gran from gran. No capacity is 
actually allocated until the first insertion, hence no errors can occur. 


The granularity is significant when an insertion requires an increase in capacity; the increase is such that 
the capacity, in records, is made an exact multiple of the granularity. Increasing the value of gran means 
that the array cell needs to be reallocated less frequently (hence less heap fragmentation) as a result of 
insertions, but more memory may be wasted in unused capacity. Any unused capacity may be recovered by 
sending a vA_compREss message when the building of an array is complete. 


VA_CAPACITY Set capacity 


VOID va_capacity(UINT nspc); 


Set the capacity of the array cell by reallocating it to have exactly the capacity for nspc records (i.e. 
nspc*vafix.rlen bytes). 


Does not alter the capacity and calls p_leave (E_GEN_NoMEMoRY) if there is not enough memory for the 
specified capacity. 


Calls p_panic (P_PANIC_P_VAFLAT_3) if nspc is less than the current number of records in the array. 


& VA_COMPRESS Compress 


VOID va_compress (VOID) 


Compress the capacity of the array to exactly that required to hold the current records. This is achieved by 
sending itself a va_capaciTy message to set the capacity to varoot .nrec records. If there are no records in 
the array, the array cell is freed as required by the varoort class. 


& VA_DELETEM Delete sequence of records 


VOID va_deletem(UINT recno, UINT nrecs); 
Delete the sequence of nrecs records starting at record recno. 


Calls p_panic (P_PANIC_P_VAFLAT_4) if recnotnrecs is greater than the number of records in the array. 


The number of records in the array, held in varoot .nrec, 1s reduced by nrecs. The delete is performed by 
copying the data of following records over the records being deleted. No allocated space is freed. 


VA_INSERTM Insert sequence of records 


VOID va_insertm(UINT recno, VOID *prec, UINT nrecs) 


Inserts the sequence of nrecs records pointed to by prec before record recno where recno is between zero 
and the number of records inclusive. 


OLIB REFERENCE 


If the array cannot currently hold all the additional records, the record capacity is set (by sending itself a 
VA_CAPACITY message) to the smallest exact multiple of the granularity that is greater than the total 
number of records to be held. The data is inserted by opening up a gap in the array (by buffer copying) 
then copying the new data into the gap. 


Inserts no records and calls p_1eave (E_GEN_NOMEMOoRY) If there is not enough memory available to hold 
the additional records. 


Calls p_panic(P_PANIC_P_VAFLAT_2) if recno is greater than the number of records in the array. 


& VA_PREC Point to record 


VOID *va_prec(UINT recno) 
Return the address of record recno. 


Calls p_panic(P_PANIC_P_VAFLAT_1) if recno is greater than or equal to the number of records in the 
array. 


& VA_PBUF Point to record data 


VOID *va_pbuf (UINT recno); 


AS VA_PREC. 


VASEG 


VAROOT VAFIX 
ae eet 


destroy va_replace va_init 
va_count va_copy va_compress 
va_delete va_reclen va_deletem 


va_sort va_swap va_insertm 


va_key va_capacity 


va_findisgq Het va_prec 
va_insertisq va_pbuf 
va_append 

va_insert 

va_search 

va_compare 

va_reset 


va_test 


The vassc class may be used to create arrays of fixed length records where the array is segmented into a 
number of equal sized blocks. The segments are allocated from the heap and are doubly linked. 


The segmented array object is suitable for large dynamically changing arrays and is substantially more 
likely to make efficient use of the available heap memory. Its disadvantage is that it takes longer to locate 
a random record by record number because it has to count through the segments. However, the object 
remembers the last record accessed so that scanning a segmented array sequentially from the first record is 
reasonably efficient. 


The segments are generally not less than 50% full. See the scpur class documentation (in the SGBUF 
Segmented Buffer Class chapter) for more information on the segmentation mechanisms. 


5 VARIABLE ARRAY CLASSES 


Class definition 


Defined in sub-category file varray.cl (generated header file varray.g). 


CLASS vaseg vafix 
Segmented fixed length variable arrays 
{ 
REPLACE va_init 
REPLACE va_compress 
REPLACE va_capacity=p_dummy 
REPLACE va_deletem 
REPLACE va_insertm 
REPLACE va_prec 
REPLACE va_pbuf=vaseg_va_prec 


PROPERTY 1 
{ 
PR_SGBUF *buf; segmented buffer 
} 
} 
Property 
vaseg.buf The object handle of the owned instance of the segmented buffer (scpur) 


class. This may be used by any subclass to access the scBur object. 


VASEG methods 
VA_INIT Initialise 


VOID va_init (UINT rlen, UINT granularity); 


Initialise the array by setting the record length to rien, creating a scBur object and initialising it with a 
segment size of rlen*granularity. Note that, since the segment size is an exact multiple of the record 
length, the content of a record will never straddle a segment boundary (significant for the va_prec and 
va_pbuf methods). 


The first segment is not allocated until the first insertion. 


Calls p_leave (E_GEN_NoMEMoRyY) if it cannot create the scpur object. 


VA_CAPACITY Set capacity 


Setting the capacity does not make any sense for the vaseg class and this method does nothing. 


& VA_COMPRESS Compress 


VOID va_compress (VOID) 


Compress the capacity of the array by sending an sB_comrEss message to the owned scBur object. 


& VA_DELETEM Delete a sequence of records 


VOID va_deletem(UINT recno, UINT nrecs); 


Delete the sequence of nrecs records starting at record recno. The delete is performed by sending an 
SB_DELETE message to the owned scBur object. 


Reduces the record count by nrecs. 


OLIB REFERENCE 


VA_INSERTM 


VOID va_insertm(UINT recno, VOID *prec, UINT nrecs) ; 


Insert a sequence of records 


Insert the sequence of nrecs records pointed to by prec before record recno, where recno is between zero 
and the number of records inclusive. The insert is performed by sending an sB_INsERT message to the 
owned scBur object. 


Increases the record count by nrecs if the insertion was successful. 


Inserts no records and calls p_leave (E_GEN_NOMEMoRY) if there is not enough memory available to hold 
the additional records. 


& VA_PREC Point to record 


VOID *va_prec(UINT recno) 
Returns the address of record number recno. 
The record pointer is obtained by sending an sp_pornt message to the owned scBurF object. 


Calls p_panic(P_PANIC_P_VASEG_1) if recno is greater than or equal to the number of records in the 
array. 


& VA_PBUF Point to record data 


VOID *va_pbuf (UINT recno) 


AS va_prec. 


VAXVAR 


VAROOT VAFIX VAFLAT 


gran 


nspc 


destroy 
va_count 
va_delete 
va_sort 


va_key 


va_findisgq 


va_insertisq 
va_append 
va_insert 
va_search 
va_compare 
va_reset 


va_test 


va_compress 


ac4 tem 
vFarinsertm 
va_capacity 
va_prec 


vwarpbut 


va_test 
va_copy 
va_reclen 
va_replace 
va_init 
va_deletem 
va_insertm 


va_pbuf 


The vaxvar class may be used to create arrays of variable length records where there is no restriction on 
the values of the bytes which can be stored within records. Each record is stored in its own heap cell and 
the records are indexed by a variat array of Rc_vAxvaR structs. 


The vaxvar class subclasses the fixed length record array vartat which provides its index. Although 
vaxvar has variable length records, only 8 of the methods inherited from variat needed to be replaced. 


In vaxvar, records are not described simply by their address but indirectly via the address of a record 
descriptor. A record descriptor is a RC_vaxvar struct that contains the address and length of a record. 


The rc_vaxvar struct is used to specify records both outside and inside the array. For example, the 
insertion methods va_append, va_insert, va_insertisg and va_insertm all require the address of an 
RC_VAXVAR Struct - and the va_prec method returns the address of an rc_vaxvar struct. 


5 VARIABLE ARRAY CLASSES 


The va_pbuf method will return a pointer to the actual data buffer (ie the Rc_vaxvar buf field). The 
va_copy method takes a buffer address (to take the copied record) rather than the address of an Rc_vaxvarR 
struct. 


When a record is inserted, a cell is allocated for the variable length record data and an index record is 
inserted - the capacity of the index may need to be increased. When a record is deleted, the record data 
cell is freed and the corresponding index record is deleted. Deletions do not automatically reduce the 
record capacity of the index but the index capacity may be reduced manually using va_compress or 
va_capacity. There is no means of controlling the capacity of the record data storage. 


On a 16-bit address machine, the overhead per record is 4 bytes for the Rc_vaxvar record and at least 2 
bytes for the allocated cell. However, any zero length records do not have an associated record value cell 
and, in this case, the corresponding but (address) field of the rc_vaxvar struct is guaranteed to be nuLL. 


The vaxvar class is suitable for short to medium length arrays or for large arrays which have a known 
maximum capacity (in terms of the number of records required). It is not suitable for arrays which can 
dynamically grow to a large number of records because the index is in a single cell. The vaxvars class 
(which has a segmented index) should be used when there is a possibility of growth to a large number of 
records. 


Compared to vastr, vaxvar has the following advantages: 
® vaxvar can store arbitrary record data, which may include zero bytes 
e random access to vaxvar records is efficient 


@ vaxvar records may be exchanged efficiently since only the corresponding index items are 
exchanged - the sort method is thus very efficient 


e the data for each record is stored in a separately allocated cell, so heap fragmentation is less 
likely to be a problem 


Compared to vastr, vaxvar has the following disadvantages: 
e the record overhead in vaxvar is at least six bytes compared to one byte in vasTR 


e the Rc_vaxvar descriptor which is used to describe a record is often less convenient than the 
address of a zero terminated string, but the va_pbuf method overcomes this quite well 


e —vaxvar records do not automatically provide a zero terminator 


Class definition 


Defined in sub-category file varray.cl (generated header file varray.g). 


CLASS vaxvar vaflat 
Indexed variable length record variable arrays - one record per heap cell 
{ 
REPLACE va_test 
REPLACE va_copy 
REPLACE va_reclen 
REPLACE va_replace 
REPLACE va_init 
REPLACE va_deletem 
REPLACE va_insertm 
REPLACE va_pbuf 
TYPES 
{ 
typedef struct 
{ 
UWORD len; record length 
UBYTE *buf; record data 
} RC_VAXVAR; 


} 
Property 


None. 


OLIB REFERENCE 


VAXVAR methods 


& VA_INIT Initialise 


VOID va_init (UINT gran) ; 


Initialise the array by supersending the va_1n1T message to the varLat object, passing the size of an 
RC_VAxvaR Structure as the record size and gran as the granularity. The subclassed variat array provides 
the index used by the vaxvar object. No capacity is actually allocated until the first insertion, hence no out 
of memory errors can occur. 


The granularity is significant when an insertion requires an increase in capacity; the increase is such that 
the capacity, in records, is made an exact multiple of the granularity. Making this value larger means that 
the index array cell needs to be reallocated less frequently (hence less heap fragmentation) as a result of 
insertions, but more memory may be wasted in unused capacity. 


& VA_TEST Compare two records by pointer 


INT va_test (VOID *precl, VOID *prec2); 


Compare the record pointed to by prec2->buf with the record at prec1->buf, on the assumption that they 
contain text, exactly as for the vaRooT va_test method. 


The basis for the comparison is subject to the contents of varoot .key, set by va_key, as follows: 


if varoot .key.1len==0 it uses 
p_scmp df varoot.key.fold is FALSE), or 
p_scmpi af varoot.key.fold is TRUE). 


if varoot .key.len>0 it uses 
p_bemp (if varoot.key.fold iS FALSE), OF 
p_bcempi af varoot.key.fold is TRUE). 


The default is to use p_scmp. 


Returns the logical equivalent of (*preci1->buf-*prec2->buf) - that is, zero if the two records are equal, 
negative if *preci->buf is before (less than) *prec2->buf, positive if after. If key. desc iS TRUE this result 
is reversed. 


& VA_DELETEM Delete a sequence of records 


VOID va_deletem(UINT recno, UINT nrecs); 
Delete the sequence of nrecs records starting at record recno. 


The process of deletion is two fold: first, the records defined by the rc_vaxvar elements are found and any 
allocated cell (buffer data) is freed; Second, the index elements are deleted by supersending a va_DELETEM 
message. 


VA_INSERTM Insert a sequence of records 


VOID va_insertm(UINT recno, RC_VAXVAR *prec, UINT nrecs); 


Insert the sequence of nrecs records pointed to by prec before record recno, where recno is between zero 
and the number of records inclusive. The record sequence pointed to by prec must be a contiguous array 
of nrecs RC_VAXVAR Structs. 


The insertion of records is a two stage process. Firstly the index entries are inserted by supersending a 
VA_INSERTM message to the varLat superclass. If this is successful, a heap cell is allocated for each record 
to be inserted, the data is copied into each cell and the cell handle written to the rc_vaxvar buf field. If an 
allocation fails, all entries made so far are removed, their allocated cells being freed. 


Inserts no records and calls p_leave (E_GEN_NOMEMoRY) if there is not enough memory available to hold all 
the additional records. 


5 VARIABLE ARRAY CLASSES 


VA_REPLACE 


VOID va_replace(UINT recno, RC_VAXVAR *prec); 


Replace record 


Replace record recno with the record described by the rc_vaxvar struct at prec, by freeing the original 
record cell, allocating a new cell of the appropriate size and replacing the index record with the new 
descriptor. 


Calls p_leave (E_GEN_NOMEMoRY) , Without modifying the original record, if there is not enough memory 
available to hold the replacement record. 


& VA_COPY Copy a record 


UINT va_copy(UINT recno, VOID *pbuf); 


Copy record number recno by supersending itself a va_copy message to get the record descriptor and then 
using p_bcpy to copy the record data to pbuf. 


Returns the length of the data copied to pbut. 


& VA_RECLEN 


UINT va_reclen(UINT recno); 


Get record length 


Returns the record length of record recno. 


& VA_PBUF Point to record data 


VOID *va_pbuf (UINT recno); 
Returns a pointer to the record data, read from the bur field of the corresponding Rc_vaxvar struct. 


It should be noted that the va_prec method (provided by the variart superclass) returns a pointer to the 
RC_VAXVAR Struct. 


VAXVARS 


VAROOT VAFIX VASEG VAXVARS 


nrec ke 


destroy ad va_test 


va_count 
va_delete 
va_sort 


va_key 


va_findisgq 


va_insertisq 
va_append 
va_insert 
va_search 
va_compare 
va_reset 


va_test 


va_compress 


a ee 
Farinsertm 
va_capacity 
va_prec 


wa pbut 


va_copy 
va_reclen 
va_replace 
va_init 
va_deletem 
va_insertm 


va_pbuf 


The vaxvars class is identical to the vaxvar class except that it subclasses the vaszc class (a segmented 
array) for its index rather than var.at (a flat array). In other words, the index records are placed in a 


segmented buffer. 


The vaxvars class should be used in preference to vaxvar when there is the possibility of a large number 


of records. 


OLIB REFERENCE 


Class definition 


Defined in sub-category file varray.cl (generated header file varray.g). 


CLASS vaxvars vaseg 
Indexed variable length record variable arrays - one record per heap cell 
Uses a segmented array for an index 


REPLACE va_test=vaxvar_va_test 
REPLACE va_copy=vaxvar_va_copy 
REPLACE va_reclen=vaxvar_va_reclen 
REPLACE va_replace=vaxvar_va_replace 
REPLACE va_init=vaxvar_va_init 
REPLACE va_deletem=vaxvar_va_deletem 
REPLACE va_insertm=vaxvar_va_insertm 
REPLACE va_pbuf=vaxvar_va_pbuf 


Property 


None. 


VAXVARS methods 


See VAXVAR methods. 


CHAPTER 6 


EDITABLE DOCUMENTS 


The EPROOT, EPFLAT and EpsEc classes provide the means of storing, reading and editing, in memory, the 
text of a document. The text must always have a terminating zero but may otherwise be of any length up 
to a maximum of 65535 characters, subject to memory constraints. 


The methods support the use of an instance of (a subclass of) EPFLAT or EPSEG as a clipboard. Text may be 
cut or copied into such a clipboard from a document or pasted from a clipboard into a document. 


Document content 
The concepts of words, paragraphs and blocks are built into the document content model, where: 


e® a paragraph is any sequence of characters delimited by a paragraph delimiter. A paragraph 
delimiter is an ASCII 0, 1, 2 or 3, a value of 0 being by far the most commonly used. The final 
paragraph delimiter in the document is always an ASCII zero. 


e aword is any sequence of characters delimited by one or more word delimiter characters. A word 
delimiter is either a paragraph delimiter, or a whitespace character (for which p_isspace returns 
TRUE). 


e a block is a sequence of paragraphs delimited by paragraphs that are either empty or, if not 
empty, contain only whitespace characters. 


The terminating ASCII zero is generally not regarded as part of the editable content. It is not, for 
example, included in the document length as returned by an ep_sense_len method. 


Its presence is fundamental to the operation of all classes that subclass EPRoot and it should never be 
deleted. 


Addressable character positions 


A position in an EPFLAT or EPSEG document is considered, in general, to mark the point between two 
adjacent characters. Thus, character position 3 is interpreted as being between the third and fourth 
characters. Character position zero is before the first character in the document. 


Inserting at position 9, say, will insert text after the ninth character: deleting the characters between 
positions 3 and 5 will delete the fourth and fifth characters. 


The last addressable character position is immediately before the final paragraph delimiter (always an 
ASCII zero). 


Usage 


Instances of (subclasses of) EPFLAT and EPsEc are widely used in all SIBO machines to contain editable 
text. Examples range from the text in a dialog edit box, to the text of a word processor document. 


In general, The epriat class should be used for small amounts of text, or for documents with a limited 
variability of content, whereas the EpsEc class should be used for larger documents, or for those with a 
wide dynamic content range. (Compare this with the recommended use of the varLat and vaszc variable 
array classes.) 


OLIB REFERENCE 


Precursors 


An understanding of the following topics would prove helpful: 
e =the p_enter and p_leave error handling services 


e for EPsEG, the scpur segmented buffer class 


Class diagram 


fees 


¢ eproot / 


~ S22) 

~ 
COS. pee fB 
¢ epflat / ~  epseg y y  sgbuf / 
> js 4.43 es ) 


Na ae Los 


Sees 


— 


EPROOT 


ep_set_text ep_sense_text 
ep_scan_word ep_capacity 
ep_word_count 


ep_scan_para ep_compress 


ep_para_count ep_init 


ep_scan_block ep_sense_len 
ep_add_para ep_sense_chars 
ep_copy_indent ep_back_chars 
ep_copy_to_front ep_insert 
ep_copy_to_back ep_delete 
ep_paste ep_extract 
ep_mod_chars ep_clear 


The Eproot abstract class provides the basic methods for manipulating the text of a document. 


6 EDITABLE DOCUMENTS 


Class definition 
Defined in sub-category file edit.cl (generated header file edit. g). 


CLASS eproot root 


Editable paragraphs (abstract class) 

{ 

ADD ep_set_text Set the contents, replacing any previous contents 

ADD ep_scan_word Scan by words 

ADD ep_word_count Return word count 

ADD ep_scan_para Scan by paragraphs 

ADD ep_para_count Return paragraph count 

ADD ep_scan_block Scan by blocks 

ADD ep_add_para Append a paragraph given its content 

ADD ep_copy_indent Copy indent from previous paragraph 

ADD ep_copy_to_front Copy range to front of provided clipboard 

ADD ep_copy_to_back Copy range to back of provided clipboard 

ADD ep_paste Paste from provided clipboard, update position 

ADD ep_mod_chars Various mods to a range of characters 

ADD ep_sense_text Copy out all the data and return its length 

ADD ep_capacity=p_dummy Adjust storage to stated capacity 

DEFER ep_compress Compress storage to minimum possible 

DEFER ep_init Prepare an empty editable object 

DEFER ep_sense_len Return length of data 

DEFER ep_sense_chars Provide pointer to following contiguous data 

DEFER ep_back_chars Provide pointer to previous contiguous data 

DEFER ep_insert Insert block of characters 

DEFER ep_delete Delete range of text 

DEFER ep_extract Extract data into buffer 

DEFER ep_clear Empty the object of all contents 

CONSTANTS 
{ 
EP_SCAN_BACKWARDS Ox01 Scan backwards if set 
EP_SCAN_STAY 0x02 Will stay put if already at a boundary 
EP_SCAN_TO_BEGIN 0x04 Stops at beginning of unit 
EP_SCAN_TO_END 0x08 Stops at end of unit 
EP_SCAN_JOIN_DELIM 0x10 Sequence of delimiters count as one 
EP_SCAN_NOT_TO_END 0x20 Do not scan past the final terminator 
EP_RETURN_LENGTH -1 special meaning for ep_sense_chars 
EP_MOD_TOLOWER 0 fold to lower case 
EP_MOD_TOUPPER 1 fold to upper case 
EP_MOD_WRAP 2 join paragraphs by converting zeros to spaces 
} 

PROPERTY 
{ 
UWORD maxlen; Maximum permissible length of text 
} 

} 

Property 
eproot.maxlen the maximum permissible length of the text. All subclasses must set this 


field, normally in an ep_init method 


EPROOT methods 
EP_SET TEXT Set content 


VOID ep_set_text (TEXT *buf, UINT len); 


Replace any existing text with a single paragraph containing 1en characters copied from *buf. The value 
of 1en should exclude any trailing paragraph terminator. 


Calls p_1eave for out of memory errors. In this event, none of the existing text will have been replaced. 


OLIB REFERENCE 


& EP_SCAN_ WORD 


Scan by word 


UINT ep_scan_word(UWORD *ppos, UINT flags); 


Scan, from character position *ppos, by one word, updating *ppos to the new character position and 
returning the number of characters skipped by the scan. There is no need for the initial position to be at a 


word boundary. 


The value of f1ags may be any combination of the following: 


EP_SCAN_BACKWARDS 


EP_SCAN_STAY 


EP_SCAN_TO_BEGIN 


EP_SCAN_TO_END 


EP_SCAN_JOIN_DELIM 


EP_SCAN_NOT_TO_END 


Scan backwards if set, otherwise scan forwards 

Do not scan if already at a word boundary 

Scan to the beginning of a word 

Scan to the end of a word 

Treat a sequence of word delimiters as a single delimiter 


Do not scan past the final terminator 


& EP_WORD COUNT 


UINT ep_word_count (VOID) ; 


Count words 


Return a count of the total number of words in the document. 


& EP_SCAN_PARA 


UINT ep_scan_para(UWORD *ppos, UINT flags); 


Scan by paragraph 


Scan, from character position *ppos, by one paragraph, updating *ppos to the new character position and 
returning the number of characters skipped by the scan. There is no need for the initial position to be at a 
paragraph boundary. 

The value of f1ags may be any combination of the following: 

EP_SCAN_BACKWARDS Scan backwards if set, otherwise scan forwards 
EP_SCAN_STAY Do not scan if already at a paragraph boundary 
EP_SCAN_TO_BEGIN Scan to the beginning of a paragraph 
EP_SCAN_TO_END Scan to the end of a paragraph 
EP_SCAN_JOIN_DELIM Treat a sequence of paragraph delimiters as a single delimiter 


EP_SCAN_NOT_TO_END Do not scan past the final terminator 


& EP_PARA_COUNT 


UINT ep_para_count (VOID) ; 


Count paragraphs 


Return a count of the total number of paragraphs in the document. 


© EP_SCAN BLOCK 


UINT ep_scan_block(UWORD *ppos, UINT flags); 


Scan by block 


Scan, from character position *ppos, by one block, updating *ppos to the new character position and 
returning the number of characters skipped by the scan. 


The initial position is assumed to be at a paragraph boundary. 


6 EDITABLE DOCUMENTS 


The value of f1ags may be any combination of the following: 


EP_SCAN_BACKWARDS Scan backwards if set, otherwise scan forwards 
EP_SCAN_STAY Do not scan if already at a block boundary 
EP_SCAN_TO_BEGIN Scan to the beginning of a block 

EP_SCAN_TO_END Scan to the end of a block 

EP_SCAN_JOIN_DELIM Treat a sequence of block delimiters as a single delimiter 
EP_SCAN_NOT_TO_END Do not scan past the final terminator 


EP_ADD_PARA Append a paragraph 


VOID ep_add_para(TEXT *buf, UINT len); 
Append a paragraph containing 1en bytes of text copied from *buf. 


The text in buf is appended more efficiently if it is supplied as a zero terminated string - when len 
should be equal to p_sien (buf) - but the terminating zero is not mandatory. 


Calls p_leave, without inserting anything, if there is insufficient memory available to append the 


paragraph. 


EP_COPY_INDENT Copy whitespace indentation 


UINT ep_copy_indent (UWORD *ppos) ; 


Copy any leading whitespace from the previous paragraph (which is assumed to exist) to the character 
position indicated by *ppos. This position will normally be the start of a paragraph. 


The value of *ppos is incremented by the number of characters inserted. 
Returns the number of characters inserted. 
Inserts nothing and calls p_1eave if there is insufficient memory to perform the insertion. 


Returns zero if the insertion is successful. The method is suitable for being called under the protection of 
p_enter. 


EP_COPY_TO_FRONT Copy range to front of clipboard 


INT ep_copy_to_front (UINT posl, UINT pos2, PR_ROOT *clip); 


Copy the range of characters between positions posi and posz2 to the front (position zero) of the clipboard 
clip, where clip is assumed to be the handle of an instance of (a subclass of) EPROOT Or EPSEG. 


Inserts nothing in the clipboard and calls p_ieave if there is insufficient memory to perform the insertion. 


Returns zero if the insertion is successful. The method is suitable for being called under the protection of 
p_enter. 


EP_COPY_TO BACK Copy range to back of clipboard 


INT ep_copy_to_back(UINT posl, UINT pos2, PR_ROOT *clip); 


Copy the range of characters between positions posi and pos2 to the back (before the terminating zero) of 
the clipboard clip, where clip is assumed to be the handle of an instance of (a subclass of) EPRooT or 
EPSEG. 


Inserts nothing in the clipboard and calls p_ieave if there is insufficient memory to perform the insertion. 


Returns zero if the insertion is successful. The method is suitable for being called under the protection of 
p_enter. 


OLIB REFERENCE 


EP_PASTE Insert from clipboard 


INT ep_paste(UWORD *ppos, PR_EPROOT *clip); 


Insert the contents of the clipboard clip, assumed to be the handle of an instance of (a subclass of) EPROOT 
Of EPSEG, at position *ppos. The value of *ppos is updated to the end of the inserted text. 


Inserts nothing and calls p_ieave if there is insufficient memory to perform the insertion. 


Returns zero if the insertion is successful. The method is suitable for being called under the protection of 


p_enter. 


& EP_MOD_CHARS Modify characters in a range 


VOID ep_mod_chars(UINT posl, UINT pos2, UINT mod); 


Modify the characters between positions pos1 and pos2. The modification depends on the value of moa, 
which may be one of: 


EP_MOD_TOUPPER convert characters to upper case, with p_toupper 
EP_MOD_TOLOWER convert characters to lower case, with p_tolower 
EP_MOD_WRAP convert each paragraph delimiter character to a space (ASCII 32) character 


& EP_SENSE TEXT Copy text to buffer 


UINT ep_sense_text (TEXT *buf); 


Copy the entire text of the document, including the terminating zero, to *buf. It is the user's responsibility 
to ensure that the buffer is of sufficient length. 


Returns the number of characters copied, excluding the terminating zero. 


& EP_CAPACITY Set document capacity 


VOID ep_capacity(UINT len); 


This method does nothing, which is the appropriate action for subclasses using segmented storage (that is, 
EPSEG or a subclass of EPSEG). 


Subclasses using storage in a single allocated segment should subclass this method (see, for example, 
EPFLAT'S ep_capacity method). 


Deferred EPROOT methods 


The deferred methods, listed below, are all fully described in the following documentation of the EPFLAT 
and Epssc Classes. 


EP_INIT Initialise 

EP_SENSE_LEN Sense document length 
EP_SENSE_CHARS Sense characters forwards 
EP_BACK_CHARS Sense characters backwards 
EP_INSERT Insert characters 
EP_EXTRACT Copy out characters 
EP_DELETE Delete characters 

EP_CLEAR Clear the document 
EP_COMPRESS Compress allocated storage 


EPFLAT 


maxlen 


ep_set_text ep_sense_text 
ep_scan_word 
ep_word_count 
ep_scan_para 
ep_para_count 
ep_scan_block 
ep_add_para 
ep_copy_indent 
ep_copy_to_front 
ep_copy_to_back 
ep_paste 
ep_mod_chars 


EPFLAT stores the document text contiguously in a single allocated cell. 


EPFLAT 


destroy 
ef_granularity 
ef_sense_buf 
ep_init 
ep_sense_len 
ep_sense_chars 
ep_back_chars 
ep_insert 
ep_extract 
ep_delete 
ep_clear 
ep_compress 
ep_capacity 


6 EDITABLE DOCUMENTS 


This class is intended for use either to store relatively small amounts of text, or where the dynamic range 


of the document size is small. 


A typical example is to store the text of a dialog edit box. 
Class definition 
Defined in sub-category file edit.cl (generated header file edit. g). 


CLASS epflat eproot 
Editable paragraphs - stored in a single allocated cell 


REPLACE 
REPLACE 
REPLACE 
REPLACE 
REPLACE 
REPLACE 
REPLACE 
REPLACE 
REPLACE 
REPLACE 
REPLACE 
ADD ef_g 
ADD ef_s 


PROPERTY 
{ 
UWOR 
UWOR 
UWOR 
TEXT 
} 

} 


Property 
epflat.alen 


epflat.gran 


epflat.len 


epflat.buf 


destroy 
ep_init 
ep_sense_len 
ep_sense_chars 
ep_back_chars 
ep_insert 
ep_extract 
ep_delete 
ep_clear 
ep_compress 
ep_capacity 
ranularity 
ense_buf 


Overwrite the default granularity 
More convenient than ep_sense_chars 


D alen; 
D gran; 
D len; 

*buf; 


length of allocated cell 
granularity to grow by 
length of text stored 
address of text buffer 


the size, in bytes, of the allocated cell. This should not be accessed by a subclass. 


the granularity, in bytes. The allocated cell is grown, when necessary, in 
multiples of this value. This should not be accessed by a subclass. 


the number of bytes of stored text. This should be treated as a read-only field by a 
subclass. 


a pointer to the start of the buffer containing the text. This should be treated as a 
read-only field by a subclass. 


OLIB REFERENCE 


EPFLAT methods 
& DESTROY Destroy 


VOID destroy (VOID) ; 


Free the allocated buffer and supersend the pestroy message. 


EP_INIT Initialise 


VOID ep_init (UINT maxlen) ; 


Initialise the instance of EPpFLat to be suitable to contain up to maxlen bytes of text (typically the text will 
not exceed that which can be displayed on a single line). 


Sets eproot .maxlen tO maxlen and epflat.gran to a default value of eight bytes. Allocates a minimum 
size buffer and inserts a single nun character. 


Calls p_leave if there is insufficient memory to allocate the buffer. 


& EP_SENSE LEN Sense document length 


INT ep_sense_len (VOID) ; 


Returns the number of characters in the document, excluding the terminating zero. 


& EP_ SENSE CHARS Sense characters forwards 


UINT ep_sense_chars (TEXT **pbuf, UINT pos, UINT n); 
Write, to *pbuf, the address of the character at position pos. 


Returns the smaller of n and the number of contiguously stored characters at *pbuf, including the zero 
that terminates the document. 


Note that for compatibility with the zpszc class, the interface to this method does not assume that the 
entire text of the document is stored contiguously. 


& EP_BACK_CHARS Sense characters backwards 


UINT ep_back_chars (TEXT **pbuf, UINT pos, UINT n); 


Write, to *pbuf, the address of the character whose position is n characters in front of position pos; if n is 
greater than the number of characters in front of position pos, the address of the first character is taken. 


Returns the number of contiguous characters at *pbuf up to, but not including, the character at position 
pos. This value will not exceed n. 


Note that, for compatibility with the Epszc class, the interface to this method does not assume that the 
entire text of the document is stored contiguously. 


EP_INSERT Insert characters 


INT ep_insert (UINT pos, TEXT *buf, UINT len); 
Insert 1en characters from *buf, at character position pos. 


If pos is -1, the characters are inserted at the end of the document (before the terminating zero). This 
feature is not replicated in the ep_insert method of the epsse class. 


Inserts nothing and calls p_ieave if there is insufficient memory to perform the insertion (with an 
E_GEN_NOMEMoRY error) or if the resulting document length were to exceed eproot .maxlen (with an 
E_GEN_OVER error). 


Returns zero if the insertion is successful. The method is suitable for being called under the protection of 
p_enter. 


6 EDITABLE DOCUMENTS 


& EP_EXTRACT Copy out characters 


VOID ep_extract (UINT pos, TEXT *buf, UINT len); 
Copy len characters to *buf, starting with the character at position pos. 
The user is responsible for ensuring that the buffer is of sufficient length to contain the text. 


Note that no check is made to ensure that 1en characters are available at position pos. 


& EP_DELETE Delete characters 


VOID ep_delete(UINT posl, UINT pos2); 


Delete the characters between positions pos1 and pos2, without making any attempt to reduce the size of 
the allocated buffer. 


If pos2 is -1 then all characters between position pos1 and the end of the document are cleared. 


If pos2 is less than or equal to pos1 then the method does nothing. 


& EP_CLEAR Clear the document 


VOID ep_clear (VOID) ; 
Remove any text. This leaves a document containing a single terminating zero. 


No attempt is made to reduce the size of the allocated buffer. 


EP_COMPRESS Compress allocated storage 


VOID ep_compress (VOID) ; 


Reduce the size of the allocated cell to the minimum required to contain the document, subject to the 
restraint of the current value of epflat.gran. The cell will never be smaller than epfiat.gran bytes in 
length. 


This method can only fail (by calling p_1eave) if it follows an ErF_GRANULARITY message that alters the 
granularity such that the ep_compress method causes the allocated cell to increase in size. In general (and 
certainly if the ef_granularity method is never called) it is safe to assume that this method will never 
fail. 


EP_CAPACITY Set document capacity 


VOID ep_capacity(UINT len); 
Set the document capacity (using £_realloc) to 1en bytes, rounded up to be a multiple of epflat.gran. 


Calls p_leave if there is insufficient memory to reallocate the cell. 


& EF_GRANULARITY Set buffer granularity 


VOID ef_granularity(UINT gran); 
Set epflat.gran to gran or, if gran 1s zero, set epflat.gran to l. 


No attempt is made to alter the current size of the allocated buffer which may, therefore, be incompatible 
with the new granularity. 


& EF_SENSE BUF Sense start of data 


UINT ef_sense_buf (TEXT **pbuf) ; 


Write, to *pbuf, the address of the first byte of the document text, returning the length of the text, 
excluding the terminating zero. 


This method, unlike ep_sense_chars, takes advantage of the fact that the whole of the text is stored 
contiguously. 


OLIB REFERENCE 


EPSEG 


EPROOT 
Ge 


ep_set_text 
ep_scan_word 
ep_word_count 
ep_scan_para 
ep_para_count 


ep_scan_block 


ep_sense_text 
ep_capacity 


ep_init 
ep_sense_len 
ep_sense_chars 
ep_back_chars 
ep_insert 


ep_extract 


ep_add_para ep_delete 


ep_clear 


ep_copy_indent 


ep_copy_to_front epiinsert 
ep_copy_to_back 


ep_compress 


ep_paste 


ep_mod_chars 


EPSEG Stores the document text in a segmented buffer using an instance of scBuF. 


This class is intended for use either to store large amounts of text, or where the dynamic range of the 
document size is potentially large. 


A typical example is to store the text of a text processor document. 


Class definition 
Defined in sub-category file edit.cl (generated header file edit. g). 


CLASS epseg eproot 
Editable paragraphs - segmented storage 


REPLACE ep_init 
REPLACE ep_sense_len 
REPLACE ep_sense_chars 
REPLACE ep_back_chars 
REPLACE ep_insert 
REPLACE ep_extract 
REPLACE ep_delete 
REPLACE ep_clear 
REPLACE ep_compress 
PROPERTY 1 

{ 

PR_SGBUF *b; 

} 


handle of buffers data 


} 
Property 


the handle of an instance of the scBur segmented buffer class in which the 
text is stored. It should be regarded as read only. 


epseg.b 


EPSEG methods 
EP_INIT 


VOID ep_init (UINT maxlen) ; 


Initialise 


Initialise, by setting eproot .maxlen tO maxlen, creating an instance of scBur and initialising it with a 
fixed granularity of 64 bytes and then inserting a single nu. character. 


Calls p_leave if there is insufficient memory. 


6-10 


6 EDITABLE DOCUMENTS 


& EP_SENSE LEN Sense document length 


UINT ep_sense_len (VOID) ; 


Returns the number of characters in the document, excluding the terminating zero. 


& EP_SENSE CHARS Sense characters forwards 


UINT ep_sense_chars (TEXT **pbuf, UINT pos, UINT n); 
Write, to *pbuf, the address of the character at position pos. 


Returns the smaller of n and the number of contiguously stored characters at *pbuf, including the zero 
that terminates the document. 


& EP_BACK_CHARS Sense characters backwards 


UINT ep_back_chars (TEXT **pbuf, UINT pos, UINT n); 


Write, to *pbuf, the address of the character whose position is n characters in front of position pos; if n is 
P P 
greater than the number of characters in front of position pos, the address of the first character is taken. 


Returns the number of contiguous characters at *pbuf up to, but not including, the character at position 
pos. This value will not exceed n. 


EP_INSERT Insert characters 


INT ep_insert (UINT pos, TEXT *buf, UINT len); 
Insert 1en characters from *buf, at character position pos. 


Inserts nothing and calls p_ieave if there is insufficient memory to perform the insertion (with an 
E_GEN_NOMEMoRY error) or if the resulting document length were to exceed eproot .maxlen (with an 
E_GEN_OVER error). 


Returns zero if the insertion is successful. The method is suitable for being called under the protection of 


p_enter. 


& EP_EXTRACT Copy out characters 


VOID ep_extract (UINT pos, TEXT *buf, UINT len); 


Copy len characters to *buf, starting with the character at position pos. The position pos must lie within 
the range of the segmented buffer or else p_panic(P_PANIC_sGBUF_1) Will be called. 


The user is responsible for supplying a buffer of sufficient length to contain the text. 


& EP_DELETE Delete characters 


VOID ep_delete(UINT posl1, UINT pos2); 


Delete the characters between positions pos1 and pos2, by sending the owned instance of scpur an 
SB_DELETE message. 


If the position pos1 lies outside the range of the segmented buffer, p_panic (P_PANIC_SGBUF_1) Will be 
called. Similarly if the position pos2 lies outside the range of the segmented buffer, 
p_panic (P_PANIC_SGBUF_2) will be called. 


& EP_CLEAR Clear the document 


VOID ep_clear (VOID) ; 


Remove any text (by sending the owned instance of scBuF an SB_DELETE message) leaving a document 
containing a single terminating zero. 


& EP_COMPRESS Compress allocated storage 


VOID ep_compress (VOID) ; 


Reduce the size of the owned instance of scpur to the minimum required to contain the document, 
consistent with its granularity of 64 bytes, by sending it an sB_compREss message. 


CHAPTER 7 


RESOURCE FILES 


RSCFILE 


pcb 

ix 
offset 
hftree 


destroy 
rs_init 


rs_read 
rs_read_buf 


The RScFILE class provides a set of services to access the contents of a resource file. Resource files are 
described in the Resource Files chapter of the Additional System Information manual. As mentioned 
there, a resource file may be embedded in an image file and may optionally be Huffman code compressed. 


An application that needs a resource file and also uses an application manager (appman) will generally 
pass the FLG_APPMAN_RSCFILE flag to the APPMAN am_init method. This causes an instance of the RSCFILE 
class to be created automatically. The application can then read resources by means of the application 
manager's am_load_resource and am_load_res_buf methods which offer greater functionality than the 
RSCFILE rs_read and rs_read_buf methods. Such users will not require detailed knowledge of the 
RSCFILE Class. 


Precursors 
The reader is assumed to understand: 

e =the p_enter and p_leave error handling services 
Class definition 


The RSCFILE class subclasses Root and is defined in the sub-category file appman.cl (with generated 
header file appman.g). 


CLASS rscfile root 
Basic access to a resource file which may be embedded in an image file 


{ 


REPLACE destroy Close channel and destroy 

ADD rs_init Open a resource file 

ADD rs_read Read a record into an allocated cell 
ADD rs_read_buf Read a record into a buffer 

TYPES 


{ 
typedef struct 
{ 
UWORD pos; Index file position 
UWORD len; Index length 
} PR_RSCFILE_HEAD; 
} 


PROPERTY 
{ 
UBYTE *pcb; resource file channel 
PR_RSCFILE_HEAD ix; header containing index position and length 
UWORD offset; file offset of start of resource data 
ULONG hftree; Huffman tree data 


} 


OLIB REFERENCE 


Property 

rscfile.pcb the currently opened resource file channel handle. It should not be 
accessed by a subclass. 

rscfile.ix the resource file header, containing the index position and length. It 
should not be accessed by a subclass. 

rscfile.offset the offset from the start of the file to the start of the resource data (zero 
unless the file is embedded in an image file). It should not be accessed by 
a subclass. 

rscfile.hftree the Huffman tree data. It should not be accessed by a subclass. 


RSCFILE methods 
J DESTROY Destroy 


VOID destroy (VOID) ; 


Close the currently opened resource file and supersend the pEstRoy message. 


RS_INIT Initialise 


INT rs_init (UBYTE *pname) ; 


Open a channel to a resource file. The string pointed to by *pname should be the name of either the 
resource file itself, or of an image file containing, in its second add-file slot, an embedded resource file. 
(See the Resource Files chapter of the Additional System Information manual.) 


Writes the appropriate values to rscfile.offset, rscfile.ix and, if the resources are Huffman encoded, 
rscfile.hftree. 


Calls p_leave on error, otherwise returns zero. The method is suitable for being called under the 
protection of p_enter. 


RS READ Allocate buffer and read resource 
INT rs_read(INT rid, UBYTE **ppdata) ; 
Allocate a buffer and read into it the resource with resource id rid. 


The length of the resource is read from the file and a buffer of this length is allocated. The resource is 
then read into this buffer and the address of the buffer is written to *ppdata. If the resource file record is 
Huffman encoded then it is decoded before being written to the buffer. 


The method calls p_leave on any error (which will be either a memory allocation error or an error while 
attempting to read the file). It is guaranteed that, on error, no memory will have been allocated and 
nothing will have been written to *ppdata. 


Returns the length of the resource, including the terminating zero if the resource is a string. 


RS READ BUF Read resource 


INT rs_read_buf (INT rid, UBYTE *buf); 


Read the resource with resource id ria into the buffer pointed to by but. If the resource file record is 
Huffman encoded then it is decoded before being written to the buffer. It is the user's responsibility to 
ensure that the buffer is of sufficient length to contain the resource. 


The method calls p_leave on error (which will be an error while attempting to read the file). 


Returns the length of the resource, including the terminating zero if the resource is a string. 


CHAPTER 8 


BINARY FILE MANAGEMENT 


The classes described in this chapter provide methods for reading and writing signatured binary files. 
Such files contain a 22 byte standard header consisting of: 

e a 16 byte file signature (all 16 bytes are significant) 

e a2 byte file version number 


e a2 byte offset from the start of the file to the end of the header (to allow for future expansion of 
the header) 


e a2 byte runtime version number 


Each version number is a hexadecimal number in the form xyyvr, where: 


x is the major version number (4 bits) 
YY is the minor version number (8 bits) 
F is the release type, A (alpha) B (beta) or F (final) 


For example, 0x123A is an alpha release of version 1.23. 


The runtime version number is intended to specify the minimum version of runtime software (for 
example, OPL) that is required to process the file. If this field is not used it should be set to zero. 


Database files are a particular type of signatured binary file. Further information relating to this type of 
file may be found in the Database Files chapter of the PLIB Reference manual and in the ISAM Reference 
manual. 

Precursors 


An understanding of the following topics would prove helpful: 
e the PLIB binary file services, as described in the Files chapter of the PLIB Reference manual. 


e =the p_enter and p_leave error handling services 


Class diagram 


om “~~ 
— — 


bfile : Co iden : 


TAN. 


{tIvfile ) serfila. / 
~ ) 


ee ce 


OLIB REFERENCE 


BFILE 


pcb 
rbuf 
rlen 
offset 


destroy 
fi_close 
fi_read 
fl_set_buf_len 
fl_sense_data 


fi_open 


fl_rewind 


The methods of the pr1z class provide the basic means of creating, opening, validating and reading 
signatured binary files with arbitrary content. 


BFILE must be subclassed to provide additional methods if it is necessary to write to the file. 


Class definition 


Defined in sub-category file tlvfile.cl (generated header file tlvfile.g). 


CLASS bfile root 
{ 
REPLACE destroy Close file then destroy 
ADD fi_close Free any buffers 
ADD fi_read Read from file into internal buffer 
ADD fl_set_buf_len Ensure internal buffer is at least len bytes 
ADD fl_sense_data Get length and address of data 
ADD fi_open Open binary file and check signature 
ADD fl_rewind Reposition to first byte after header 
CONSTANTS 
{ 
OP_BFILE_ID_SIZE 16 size of text ID 
} 
TYPES 


{ 


typedef struct 


{ 


TEXT fid[OP_BFILE_ID_SIZE]; plain text application ID 


UWORD vers; file version number 
UWORD offset; abs. file offset to end of header 
UWORD rtvers; minimum runtime version 


} 

} 

PROPERTY 
{ 
UBYTE 
UBYTE 
UWORD 
UWORD 
} 

} 


Property 


bfile.pcb 


bfile.rbuf 
bfile.rlen 


bfile.offset 


OP_BFILE_FSIG; 


*pcb; File channel 

*rbuf; Allocated record buffer 

rlen; Length of data in read buffer 
offset; 


the handle of a currently open file, or nun. It should not be accessed by 
any subclass. 


a pointer to an allocated buffer into which file data is read. 
the number of bytes of valid data in the allocated buffer. 


the byte offset from the start of the current file to the first byte after the 
file signature. 


8 BINARY FILE MANAGEMENT 


BFILE methods 
& DESTROY Destroy 


VOID destroy (VOID); 


Send an FI_cLosE message and then supersend the DEsTRoy message. 


Fl_OPEN Open file 


INT fi_open(TEXT *pname, UINT mode, OP_BFILE_SIG *psig) ; 


Open the binary file whose full file specification 1s pointed to by pname. The value of mode may be any 
combination of the PLIB file mode flags appropriate for a binary file (it must include p_rsTREAM or, more 
rarely, P_FSTREAM_TEXT). 


If a new file is being opened (mode contains either P_FCREATE Or P_FREPLACE) the file signature at «psig is 
written to the newly opened file. Otherwise, the file signature is read from the file and compared with the 
file signature at *psig. If the file signature read from the file is the wrong length, or if the two 16-byte file 
IDs do not match exactly (all sixteen bytes are compared) p_leave (E_FILE_INVALID) is called. The 
validation of the remaining signature fields will vary with the application and is left to the caller. To 
facilitate this validation, the signature read from the file is written to *psig. 


Once the file has been successfully opened, the file offset to the first byte following the file header 
(psig->offset) is written to bfile.offset. 


Returns zero if successful, or a negative error number for any error other than the E_FILE_INVALID error 
described above. 


& FI_CLOSE Close file 


VOID fi_close (VOID) ; 
Close any open file, freeing any allocated buffer. 


It is safe to send an FI_CLOSE message even if there is no open file. 


Fl_READ Read from file 


INT fi_read(UINT len); 
Read len bytes from the current position in the currently open file into the allocated buffer. 


Sends an FL_SET_BUF_LEN message to ensure that the buffer has room for at least 1en bytes before reading 
the data. If this fails, p_1eave (E_GEN_NOMEMORY) is called. 


If the read is successful, sets bfile.rlen to contain the number of bytes read into the buffer. 


Returns the number of bytes read, or a negative error. 


FL_SET BUF_LEN Set buffer size 


VOID fl_set_buf_len(UINT len); 


Reallocate, if necessary, the allocated buffer pointed to by bfile.rbuf to ensure that it has room for at 
least 1en bytes. This method will never reduce the size of the buffer. 


Calls p_leave if there is insufficient memory to reallocate the buffer. 


OLIB REFERENCE 


& FL_SENSE DATA Sense record data 


UINT fl_sense_data(UBYTE **pbuf) ; 


Write to *pbuf the address of the allocated buffer and return the length of the data last read into it by the 
fi_read method. 


The return value will be zero and the value written to *pbuf will be nut if there is no currently open file, 
or if no FI_READ message has been received. 


FL_REWIND Reposition to start 


VOID fl_rewind (VOID) ; 


Set the current file position to the first byte after the file header. 


TLVFILE 


TLVFILE 


rbuf 
rlen 
offset 


destroy fi_open 
fi_close l1_rewind 
fi_read l_write_rec 
fl_set_buf_len 


fl_sense_data 


_delrec 
_—count 
_read_by_type 
_set_rec 


1 sense_rec 


FoFH FH FH FH Fh EF SF 


l_replace 


The TLvr1.e class provides support for signatured binary files that contain type-length-value (TLV) 
records. 


Following the standard header, the file is considered to be made up of records, each of which has a 2 byte 
header specifying the record type and length. The most significant nibble of the word contains the record 
type, in the range 0-15. The remaining three nibbles contain the record length and is, therefore, restricted 
to a maximum of 4K bytes. 


Records of type 0 are considered to be deleted records. Records of type 15 (OxOf) are reserved to represent 
non-valid records and are treated as though they are deleted records. 


For efficient record access, the record number of the next record to be read and the current file position 
are stored in property. 


TLV files are designed to be Flash-friendly, i.e. they may be stored and manipulated efficiently in Flash 
SSDs (or any other EPROM medium). A TLV file stored on such a medium may be modified by 
appending, deleting or replacing records without having to make a new copy of the entire file. 


Although TLV files may contain in excess of 4,000,000,000 records, TLVF ILE is ideally suited to 
manipulating files which contain a relatively small number of records. If the file contains a large number 
of records, operations which involve non-sequential access may take an extended time to return. 


Database files are a form of TLV file with a particular file signature header and specific record content. 
Alternative means of manipulating such files are described in the Database Files chapter of the PLIB 
Reference manual and also in the ISAM Reference manual. 


Class definition 


8 BINARY FILE MANAGEMENT 


Defined in sub-category file tlvfile.cl (generated header file tivfile. g). 


CLASS tlvfile bfile 


{ 


REPLACE fi_open 
REPLACE fl_rewind 


ADD 
ADD 
ADD 
ADD 
ADD 
ADD 
ADD 


CONS 


TYPE 


PROP 


} 


Property 


fl_write_rec 


Open file 
Reposition to first record, reset property 
Write a TLV record 


fl_delrec Delete a record 
f1l_count Get record count 
fl_read_by_type Read record of specified type 
fl_set_rec Set the current record number 


fl_sense_rec 


fl_replace 


Sense the current record number 
Replace a record 


TANTS 

TLV_TYPE_UNKNOWN 0x10 
TLV_TYPE_INVALID Ox0f 
TLV_TYPE_DELETED 0x00 
TLV_TYPE_NORMAL 0x01 
TLV_TYPE_FIELDS 0x02 
TLV_TYPE_SHIFT 12 
TLV_TYPE_MASK Oxf000 
} 

Ss 


typedef struct 


{ 


OP_BFILE_FSIG fsig; Binary file signature 
UWORD types; Valid types 
} OP_TLVFILE; 


typedef struct 


{ 


UBYTE 


UINT len; 
INT type; 
} OP_TLV_REC; 


ERTY 
{ 

UWORD 
UWORD 
UWORD 
ULONG 
ULONG 
} 


tlvfile.typmask 


tl 


ae 


tl 


ti 


lvfil 


lvfil 


lvfil 


le. hdlen 


le.hdt 


le.pos 


lvfil 


ype 


le.fpos 


typmask; 
hdlen; 
hdtype; 
Pos; 
fpos; 


*Du Es. 


valid record type mask 

length of header 

type from header 

Next record to be read 

Current file position, for validation 


which record types are considered valid. For example, the value 0x32 (bits 
1, 4 and 5 set) indicates that records of type 1, 4 and 5 are valid. Records 
of other types are treated as if they do not exist. 


the current record length as decoded from the first word of the record. It 
should not be accessed by a subclass. 


the current record type as decoded from the first word of the record. It 
should not be accessed by a subclass. 


the current record number that corresponds to the file position, 
tlvfile.fpos. It should not be accessed by a subclass. 


the current file position. It should not be accessed by a subclass. 


OLIB REFERENCE 


TLVFILE methods 


All methods which read a record assume that the current file position is at the start of a record. 


Fl_OPEN Open TLV file 


INT fi_open(TEXT *fspec, UINT mode, OP_TLVFILE *psig): 


Open the TLV file whose full file specification is pointed to by fspec. The value of mode may be any 
combination of the PLIB file mode flags appropriate for a binary file (it must include p_rsTREaAM). 


Opens the file by supersending the r1_oPzn message which, if opening an existing file, validates the 16- 
byte file signature ID and overwrites psig->fsig (but not psig—>types) with the signature read from the 
file. 


Calls p_ieave if the file signature validation fails. 


Sets tlvfile.typmask to the value of psig->types and sends itself an rL_REWIND message to position to 
the start of the first record. 


Returns zero if successful or error values as returned by the Br1Lz superclass. 


FL_REWIND Reposition to start 
VOID fl_rewind (VOID) ; 
Position to the first byte following the file signature. 


Supersends the rL_REwIND message and then sets tivfile.fpos tO bfile.offset, and tlvfile.pos to 
zero. 


Calls p_1eave on error. 


FL_COUNT Count records 


VOID fl_count (ULONG *pcount) ; 


Write to *pcount the number of valid records (those whose types are specified by tivfile.typmask) in the 
file. 


Counts the records by scanning the entire file and then sends an rL_REWIND message to reposition to the 
first record. 


Calls p_leave on error. 


FL_WRITE_REC Write a record 


VOID fl_write_rec(UBYTE *buf, UINT len, UINT type); 
Append a new record of type type, containing the first 1en bytes of the data pointed to by bue. 
If any error occurs, the record is either not written or is marked as not being a valid record. 


All errors result in p_leave being called. 


FL_SET REC Set current record 


INT fl_set_rec(UINT lsw, UINT msw); 
INT fl_set_rec(ULONG recnum) ; (conceptual) 


Position to, and read into the internal buffer, record number recnum (counting only records of types 
specified by t1vfile.typmask). The uLONG recnum is actually passed in the message as two UINT 
parameters, 1sw (least significant word) and msw (most significant word). 


Returns the positive record type if successful, or =_F1LE_koF if reading past the end of the file. Other file 
errors result in a call to p_leave. The content of the internal buffer is unpredictable in the event of an 
error. 


8-6 


8 BINARY FILE MANAGEMENT 


& FL_SENSE REC Sense current record number 


VOID fl_sense_rec(ULONG *prec); 
Write, to *prec, the record number of the record following the one which has last been read. 


Writes zero if no records have been read since the receipt of an FL_REWIND message. 


FL_DELREC Delete a record 


VOID fl_delrec(UINT lsw, UINT msw); 
VOID fl_delrec(ULONG recnum) ; (conceptual) 


Delete record recnum (counting only records of types specified by t1vfile.typmask) by overwriting its 
record type with type 0. The uLonc recnum is actually passed in the message as two uINT parameters, 1sw 
(least significant word) and msw (most significant word). 


Calls p_1eave on error, in which case the record may not have been deleted. It is the user's responsibility 
to determine whether the record has been deleted (for example, by testing the number of records). 


FL_REPLACE Replace a record 


VOID fl_replace(UINT lsw, UINT msw, OP_TLV_REC *prec); 
VOID fl_replace(ULONG recnum, OP_TLV_REC *prec); (conceptual) 


Replace a record by deleting record recnum (counting only records of types specified by tivfile.typmask) 
and then appending the record specified by prec. The uLoNG recnum is actually passed in the message as 
two UINT parameters, 1sw (least significant word) and msw (most significant word). 


Deletes the record by sending itself an rL_pELETE message and, if this is successful, appends the new 
record by sending itself an FL_wRITE_REC message. 


Calls p_leave on error, in which case the original record may not have been deleted. If it has been 
deleted, the new record will either not have been appended or will have been marked as not being a valid 
record. 


FL_READ BY_TYPE Read record of specific type(s) 


INT fl_read_by_type(UINT type); 


Search forwards from the current file position and read into the internal buffer the first record whose type 
is one of those specified by the bitmask in type irrespective of the types specified by tivfile.typmask. 


Returns the record type of the record or, if the end of the file is reached before finding a record of a 
matching type, it returns E_FILE_EOF. 


Calls p_1eave for all other errors. 


This method should be used with caution. If it skips records that would normally be read (because they are 
included in t1ivfile.typmask) it may result in tivfile.pos containing an incorrect value. If there is any 
doubt, this method should always be followed by the sending of an rL_REWIND message. 


OLIB REFERENCE 


TLVDATA 


TLVDATA 


td_open 
td_save 
td_changed 
td_load_item 
td_save_item 
td_reset 


td_set_file 
td_set_item 
td_sense_item 


The tivpata abstract class provides the basic mechanisms for manipulating data that is stored in a series 
of records (each with a different record type) in a TLV file. 


Class definition 
Defined in sub-category file tlvfile.cl (generated header file tlvfile.g). 


CLASS tlvdata root 


Data which is loaded and saved to a tlvfile 
{ 
ADD td_open Open file or revert to file 
ADD td_save Save modifications to file 
ADD td_changed Return TRUE if data changed since load 
ADD td_load_item Load an item 
ADD td_save_item Save an item 
ADD td_reset=p_dummy Clear data structures 
DEFER td_set_file Set the file characteristics 
DEFER td_set_item Set an item 
DEFER td_sense_item Sense an item 
TYPES 
{ 
typedef struct 
{ 
OP_TLVFILE tlvfile; File signature and mask 
TEXT ext[6]; Default extension 
} PR_TLVDATA_CHARS; 
} 
PROPERTY 1 
{ 
PR_TLVFILE *tlv; Handle to tlvfile 
UWORD cl_tlv; Clean id for tlv file 
UWORD changed; TRUE if data changed since load 
WORD index; Index for load and save 
WORD tmask; Valid record mask 
TEXT name [P_FNAMESIZE]; Parameter file name 
} 
} 
Property 
tlv the handle of a temporary instance of the TLvr1ue class. It should not be 
accessed by a subclass. 
cl_tlv the cleanup id for the TLvF1Lz instance, used for roll-back on error. It 


should not be accessed by a subclass. 


8 BINARY FILE MANAGEMENT 


changed a flag indicating that the data has changed since a previous load or save. 
A subclass must set this to TRUE to signal that changed data requires 
saving. A subclass is not expected to set a FALSE value. 


index the type of the last record for which data has been sensed by the 
td_save_item method. It should not be accessed by a subclass. 

tmask the mask of valid record types. It should not be accessed by a subclass. 

name the full file specification of the file last used in the tad_open method. It 


should not be accessed by a subclass. 


TLVDATA methods 
TD_OPEN Open and read file 


INT td_open(TEXT *name) ; 
Open a TLV file, read all its records into memory, overwriting any existing data, and close it again. 


Sends itself a r>D_RESET message and then opens, reads and closes the file specified by name. If name is 
NULL, the file opened by a previous td_open Or td_save is reopened, otherwise name should point to a 
string containing the name of the file to open. 


Before opening the file, a T>_sET_FILE message is sent to determine the appropriate file characteristics 
and extension. If not nut, the passed name is parsed (the related name being the file extension resulting 
from the Tp_sET_FILE message) into the t1vdata.name buffer. 


An instance of TLVFILE 1s created and used to open the file and read each record in turn. As each record is 
read, a TD_LOAD_ITEM message is sent, to store the record's content. When all the records have been read 
the TLVFILE instance is destroyed (which automatically closes the file). On successful conclusion the value 
of tlvdata.changed iS Set tO FALSE. 


Returns zero if successful, or E_r1LE_nx1st if the specified file does not exist. 


All other errors result in p_leave being called. 


TD_SAVE Save data to file 


VOID td_save (TEXT *name) ; 


Write the current data to the TLV file specified by name, replacing any existing file. If name is nuLL, the 
file opened by a previous td_open or td_save is reopened, otherwise name should point to a string 
containing the name of the file to open. 


Before opening the file, a Tt>_sET_FILE message is sent to determine the appropriate file characteristics 
and extension. If not nut, the passed name is parsed (the related name being the file extension resulting 
from the TD_SET_FILE message) into the t1vdata.name buffer. 


An instance of TLVFILE 1s created and used to open the file (to replace any existing file) and write the 
records. The data, length and type of each record is determined by sending a Tp_savE_ITEM message. 
When this message returns zero, indicating that there are no further records, the TLvFILE instance is 
destroyed (which automatically closes the file). On successful conclusion the value of t1vdata.changed 1S 
set tO FALSE. 


Any error results in p_leave being called. 


& TD_CHANGED Check if changed 


INT td_changed (VOID); 


Return TRuzE if the data has been changed since a load or a save. 


OLIB REFERENCE 


TD_LOAD ITEM Process a record read from a file 


VOID td_load_item(INT type, UBYTE *buf, UINT len); 


Process the record by sending a TD_SET_ITEM message. 


TD_SAVE_ITEM Get a record to be saved 


INT td_save_item(UBYTE **pbuf, UWORD *plen); 
Determine the type of the next record to be saved and send a Tp_sENSE_ITEM message to sense its data. 
The method uses tivdata.index and tlvdata.tmask to identify the record type. 


Returns the record type, or zero if there are no further records to be saved. 


& TD_RESET Reset all data 


VOID td_reset (VOID) ; 


The supplied method does nothing. It is expected to be subclassed to perform any appropriate reset action. 


Deferred TLVDATA methods 


TD_SET FILE Set the TLV file characteristics 


VOID td_set_file(PR_TLVDATA_CHARS *pfc)j; 


Write the appropriate TLV file signature header (including the mask of valid record types) and file 
extension to the PR_TLVDATA_CHARs Struct pointed to by pfc. 


On entry, pfc->ext [0] contains the character '.' and pfc->tlvfile.fsig.offset is already set to 
sizeof (OP_BFILE_FSIG). All other bytes are set to zero. 


TD_SET_ITEM Set in-memory data for a record 


VOID td_set_item(INT type, VOID *buf, UINT len); 


Store, in memory, the data for a record of type type and of length 1en, pointed to by buf. 


TD_SENSE_ITEM Sense in-memory data for a record 
INT td_sense_item(INT type, VOID **pbuf) ; 
Write to *pbuf a pointer to the data for a record of type type. 


Returns the length of the data. 


SERFILE 


TLVDATA 


td_open 
td_save 
td_changed 
td_load_item 


SERFILE 


serial 
modem 
inkdvr 
serdvr 
file 


td_reset 
td_set_file 
td_set_item 
td_sense_item 


8 BINARY FILE MANAGEMENT 


td_save_item 


The serFr1.e class provides the methods for manipulating serial port parameter data saved in a .trm TLV 
file. 


Class definition 
Defined in sub-category file tlvfile.cl (generated header file tivfile. g). 


CLASS serfile tlvdata 
{ 
REPLACE td_reset Set defaults 
REPLACE td_set_file Set the file characteristics 
REPLACE td_set_item 
REPLACE td_sense_item 


Set an item 
Sense an item 


CONSTANTS 
TE_MASK_SERIAL 0x0001 
TE_MASK_MODEM 0x0002 
TE_MASK_FILE 0x0004 
TY_SERFILE_SERIAL 1 
OBSOLETE_SERFILE_MODEM Z 
TY_SERFILE_FILE 3 
TY_SERFILE_NEW_MODEM 4 
TY_SERFILE_SERDVR 5 
TY_SERFILE_LNKDVR 6 
TE_XMDM_NONE 3 
TE_DIAL_PULSE 1 
TE_DIAL_TONE 2 
TE_MODEM_300 0x01 
TE_MODEM_1200 0x02 
TE_MODEM_2400 0x03 
TE_MODEM_4800 0x04 
TE_MODEM_9600 0x05 
TE_MODEM_19200 0x06 
MAX_DEVICE_NAME 10 ! TTY.AS5:A plus zero terminator 
MAX_MODEM_CMD 40 


} 


OLIB REFERENCE 


TYPES 

{ 

typedef struct 
{ 
! Serial port 
P_SRCHAR ch; Serial port characteristics 
TEXT port [P_MAXDEVNAME+2]; Serial port to use 
} PF_SERIAL; 

typedef struct 
{ 
! New Modem driver 
P_MDMCHR mch; 


UBYTE phone[25]; Phone number 

UBYTE auto_dial; TRUE if modem to auto dial on connection 
UBYTE mdmdvr [MAX_DEVICE_NAME]; Modem driver to use (if any) 

UBYTE mdmcmd [MAX_MODEM_CMD]; Max extra configuration for modem 


UBYTE spare[16]; 
} PF_MODEM; 
typedef struct 
{ 
! File transfer 
UWORD protocol; File transfer protocol 
} PF_FILE; 


typedef struct 
{ 
! New Serial port 
P_SRCHAR ch; Serial port characteristics 
UBYTE serdvr[MAX_DEVICE_NAME]; Serial driver to use 
UBYTE spare[16]; 
} PF_SERDVR; 

typedef struct 
{ 
! Link drivers 
UBYTE masdvr [MAX_DEVICE_NAME]; Media access driver to use 
UBYTE lnkdvr[MAX_DEVICE_NAME]; Link driver to use 
UBYTE spare[16]; 
} PF_LNKDVR; 

} 

PROPERTY 

{ 

PF_SERIAL serial; 

PF_MODEM modem; 

PF_FILE file; 

PF_LNKDVR Inkdvr; 

PF_SERDVR serdvr; 

} 

} 


Property 

Each item of property represents the data that may be stored in a record of a serial parameter .trm file. 
serfile.serial the data for a serial port record, of record type Ty_SERFILE_SERIAL. 
serfile.modem the data for a modem driver record, of record type 


TY_SERFILE_NEW_MODEM. 
serfile.file the data for a file transfer record, of record type Ty_SERFILE_FILE. 


serfile.inkdvr the data for a link and media access driver record, of record type 
TY_SERFILE_LNKDVR. 


serfile.serdvr the data for an extended format serial driver record, of record type 
TY_SERFILE_SERDVR. 


8 BINARY FILE MANAGEMENT 


SERFILE methods 


& TD_RESET Reset all data 
VOID td_reset (VOID); 

Set the serial data to its default values and then set tivdata.changed tO TRUE. 

Sets the property data as follows: 


serfile.serial 


ch. hand P_OBEY_XOFF | P_SEND_XOFF|P_IGN_CTS 
ch.frame P_DATA_8 

ch.tbaud P_BAUD_9600 

ch.rbaud P_BAUD_9600 

ch.xon 0x11 (DC1) 

ch. xoff 0x13 (DC3) 

ch. flags P_IGNORE_PARITY 

port WTTY SA". 


serfile.modem 
mch. supported P_SRINQ_300|P_SRINQ_1200|P_SRINQ_2400|P_SRINQ_4800|P_SRINQ_9600|P_SR 
mch.baudrate INQ_19200 
mch.chand P_BAUD_2400 
mch.options P_OBEY_DSR|P_FAIL_DSR|P_OBEY_DCD|P_FAIL_DCD|P_OBEY_XOFF |P_SEND_XOFF 
P_MDM_NO_MODULATION 


serfile.file 
protocol TE_XMDM_NONE 


serfile.serdvr 


ch.hand P_IGN_CTS 
ch.frame P_DATA_8 
ch.tbaud P_BAUD_19200 
ch.rbaud P_BAUD_19200 
serdvr WT AP 


serfile.lnkdvr 
masdvr "MAS:" 
inkdvr ®LECE* 


All fields not explicitly mentioned above are zero-filled. 


& TD_SET FILE Set the serial file characteristics 


VOID td_set_file(PR_TLVDATA_CHARS *pfc); 


Set the serial file signature, extension and record type mask in the pR_TLVDATA_cHARS Struct pointed to by 
pfc. 


The file signature is set to "TRM FILE" (with the remainder of the 16 bytes zero-filled) and the file name 
extension to ". TRM". The type mask is set for record types Ty_SERFILE_SERIAL, TY_SERFILE_NEW_MODEM, 
TY_SERFILE_FILE, TY_SERFILE_SERDVR and Ty_SERFILE_LNKDVR. 


& TD SET ITEM Set in-memory data for a record 


VOID td_set_item(INT type, VOID *buf); 


Set the contents one of the five items of property corresponding to the record of type type, from the 
contents of *buf, where type is one of Ty_SERFILE_SERIAL, TY_SERFILE_NEW_MODEM, TY_SERFILE_FILE, 
TY_SERFILE_SERDVR OF TY_SERFILE_LNKDVvR and buf correspondingly points to a pF_SERIAL, PF_MODEM, 
PF_FILE, PF_SERDVR OF PF_LNKDVR Struct. 


Sets tivdata.changed tO TRUE. 


8 - 13 


OLIB REFERENCE 


& TD SENSE ITEM Sense in-memory data for a record 


INT td_sense_item(INT type, VOID **pbuf) ; 


Write to *pbur the address of one of the five items of property corresponding to the record of type type, 
where type is one of Ty_SERFILE_SERIAL, TY_SERFILE_NEW_MODEM, TY_SERFILE_FILE, 
TY_SERFILE_SERDVR OF TY_SERFILE_LNKDvr. The address written to *pbuf is a corresponding pointer to a 
PF_SERIAL, PF_MODEM, PF_FILE, PF_SERDVR Of PF_LNKDvR Struct. 


Returns the length of the record data. 


CHAPTER 9 


THE CLEANUP CLass 


VAROOT VAFIX VAFLAT CLEANUP 


nrec key rlen gran level 
nspc 
base 

destroy vwarrepiace 


va_replace | va_init destroy 


va_count va_copy va_compress cl_init 


va_delete va_reclen va_deletem cl_add 


va_sort va_swap va_insertm cl_remove 


va_key 


va_findisgq 


va_insertisq 


va_capacity 
va_prec 


va_pbuf 


cl_clean_item 
cl_clean_level 
cl_set_level 


va_append 
va_insert 
va_search 
va_compare 
va_reset 


va_test 


The cLeanup class supplies one of the main mechanisms by which resources may be released following an 
error condition. 


A typical use is in a case where a program allocates, say, a sequence of cells which must either exist as a 
whole or not at all. If, during the allocate sequence, one of the later allocations fails, the previously 
allocated cells must be freed. 


The recovery process can be simplified if each cell is placed in a cleanup list as it is allocated. Once the 
whole sequence of allocations is complete the items may be removed from the list. If, however, there is a 
failure in one of the later stages, the previously allocated cells can be freed by the sending of, for example, 
a single CL_CLEAN_LEVEL message. Note that the process of adding an item to the cleanup list is so 
arranged that the addition itself can never fail due to shortage of memory. 


Normally, an instance of the cLEanup class is created as a component of the application manager (see the 
Application Manager chapter of this manual). In this case the cleaning up of partially complete 
allocations is generally handled automatically whenever an error occurs and the programmer's 
responsibility is reduced to adding items to, and removing items from, the cleanup list at the appropriate 
times. 


Because the addition and removal of items from a cleanup list that is a component of the application 
manager is so common, a set of convenience functions are provided. These are described in a separate 
section at the end of this chapter. 


Precursors 


The reader is assumed to understand: 
e variable arrays of fixed length records 


e =the p_enter and p_leave error handling services 


OLIB REFERENCE 


Class diagram 


Class definition 


ae ae 
¢ Varoot / 
as ) 
bee 
aon ae 
( Vafix / 
~ Sash 
Me 
A ee 
( Vaflat / 
) 
eee 
(cleanup / 
= ) 
eee 


Defined in sub-category file appman.cl (generated header file appman.g). 


CLASS cleanup vaflat 


{ 


REPLACE destroy 


ADD 
ADD 
ADD 
ADD 
ADD 
ADD 


cl_init 

cl_add 
cl_remove 
cl_clean_item 
cl_clean_level 
cl_set_level 


CONSTANTS 


TYPES 


} 


typedef struct 


typedef struct 


} 


PROPERTY 


} 


Property 


{ 
UWORD level; 
} 


cleanup.level 


Destroy all items in cleanup list 
Initialise cleanup table 

Add an item for cleanup 

Remove an item (without cleanup) 
Clean up an item 

Clean up all items at current level 
Set the cleanup level 


TY_CLEANUP_DYL -5 A dyl handle 

TY_CLEANUP_SHARED -4 A shared allocated cell 
TY_CLEANUP_VOID -3 Already cleaned up 

TY_CLEANUP_ALLOC -2 An allocated cell 

TY_CLEANUP_IOCHAN -1 An IO channel 

TY_CLEANUP_OBJECT 0 An object (O_DESTROY method number !!) 


BYTE type; Type of resource 
UBYTE level; Cleanup level 
HANDLE h; Handle of resource 


RC_CLEANUP; 


UWORD nref; 
SHARED_ALLOC; 


current cleanup level 


the current cleanup level; set by c1_set_1leve1 and used by 
elclean_level 


9 THE CLEANUP CLASS 


CLEANUP Methods 
J DESTROY Destroy 


VOID destroy (VOID) ; 


Clean up all items in the cleanup list and supersend a pEsTRoy message. 


CL_INIT Initialise list 


VOID cl_init (UINT num); 
Initialise the cleanup list. 


Sends itself a va_inrT message to initialise the array for records of length sizeof (RC_CLEANUP), With a 
granularity of num. Then sends itself a va_capacitTy message to set the capacity to num records and ensures 
that the array contains at least one empty cleanup slot (of type Ty_cLEANUP_VvoID). 


CL_ADD Add item 


UINT cl_add(UINT type, HANDLE h); 
Add an item to the cleanup list of type type and handle h to the cleanup list at the current cleanup level. 


The possible values of type are: 


TY_CLEANUP_OBJECT h is the handle of an object, as returned by p_new 

TY_CLEANUP_IOCHAN h is the pointer to the channel control block, as set by p_open 

TY_CLEANUP_ALLOC h is the pointer to the allocated cell, as returned by p_alloc 

TY_CLEANUP_SHARED h is the pointer to a shared allocated cell, as returned by p_alloc (the first 
word of a shared allocated cell is assumed to contain a usage count) 

TY_CLEANUP_DYL h is the category handle of a loaded dynamic library, as set by p_loadlib 


All other values of type, except for Ty_cLEANUP_VvOID, are assumed to relate to objects and behave in a 
way similar to Ty_cLEANUP_oBJECT. In all such cases h is assumed to be the handle of the object as 
returned by p_new. When such an item is cleaned up, it is sent a message with message number equal to 
the value of type. The value ry_cLEanup_oBuectT (0) is chosen specifically to correspond to a DESTROY 
message. 


A subclasser who adds further types should respect the current scheme by using a negative number for 
each new type leaving positive numbers to represent object message numbers. 


Returns an index number which identifies the newly added item in the cleanup list. 


The cl_add method may call p_leave (f_GEN_NOMEMoRY), but not until after the current item has been 
added to the cleanup list. Thus an item cannot be 'lost' by a failure when adding it to the cleanup list. 


J CL_ REMOVE Remove item 


VOID cl_remove (UINT num); 


Remove the item specified by num (as returned by an earlier cL_app message) from the cleanup list without 
cleaning up its associated resource(s). 


The item is removed by setting its type to Ty_cLEANUP_vorp. No memory is freed. 


JCL_CLEAN ITEM Delete item 


VOID cl_clean_item(UINT num); 


Clean up the resource(s) associated with item num (as returned by an earlier cL_app message) and remove 
the item from the cleanup list. 


OLIB REFERENCE 


The cleanup action depends on the type of the item as follows: 


TY_CLEANUP_IOCHAN close the channel, using p_close 

TY_CLEANUP_ALLOC free the allocated cell, using p_free 

TY_CLEANUP_SHARED decrement the usage count of the shared allocated cell and, if decremented to 
zero, free the cell 

TY_CLEANUP_DYL unload the dynamic library, using p_unloadlib 


All other values are assumed to relate to an object and the object is sent a message with message number 
equal to the type. The special case of type Ty_cLEANUP_oBJEcT (0) corresponds to the sending of a DEsTRoY 
message. 


No allocated memory associated with the cleanup list's array is freed, but the item's type is set to 
TY_CLEANUP_vorn So that it is available for re-use. 


J CL_CLEAN LEVEL Delete all items at current level 


VOID cl_clean_level (VOID); 


Clean up all items that have been added at the current cleanup level (by sending a series of 
CL_CLEAN_ITEM messages). 


JCL_SET LEVEL Set cleanup level 


VOID cl_set_level(UINT level); 


Set the current cleanup level, stored in cleanup. level, tO level. 


CLEANUP convenience functions 


These convenience functions assume that an instance of the cLEanup class has been created during the 
initialisation of an instance of the application manager, and that its handle is stored in the application 
manager's property appman.clean. An application should ensure that the application manager's property 
is accessible via the 'magic static’ w_am. 


cl_add Add an item 


INT cl_add(INT type, VOID *p); 
Add an item, with handle p and of the specified type, to the cleanup list. The value of type may be one of: 


TY_CLEANUP_OBJECT 
TY_CLEANUP_IOCHAN 
TY_CLEANUP_ALLOC 
TY_CLEANUP_SHARED 
TY_CLEANUP_DYL 


Calling this function is equivalent to: 
p_send4 (w_am—->appman.clean,O_CL_ADD,type,p) ; 
Returns an index number which identifies the newly added item in the cleanup list. 


The function may call p_leave (E_GEN_NOMEMOoRY) , but not until after the item has been added to the 
cleanup list. 


cl_add_ object Add an object 


INT cl_add_object (VOID *p); 
Add an object, with handle p, to the cleanup list. 
Calling this function is equivalent to calling: 


cl_add(TY_CLEANUP_OBJECT,p) ; 


9 THE CLEANUP CLASS 


Returns an index number which identifies the newly added item in the cleanup list. 


The function may call p_leave (E_GEN_NOMEMOoRY) , but not until after the item has been added to the 
cleanup list. 

cl_add_iochan Add an I/O channel 
INT cl_add_iochan (VOID *p); 

Add an I/O channel, with handle p, to the cleanup list. 

Calling this function is equivalent to calling: 


cl_add(TY_CLEANUP_IOCHAN, p) ; 


Returns an index number which identifies the newly added item in the cleanup list. 


The function may call p_leave (E_GEN_NOMEMOoRY) , but not until after the item has been added to the 
cleanup list. 


cl_add_alloc Add an allocated cell 
INT cl_add_alloc(VOID *p); 
Add an allocated heap cell, with handle p, to the cleanup list. 


Calling this function is equivalent to calling: 


cl_add (TY_CLEANUP_ALLOC, p) ; 
Returns an index number which identifies the newly added item in the cleanup list. 


The function may call p_leave (E_GEN_NOMEMOoRY) , but not until after the item has been added to the 
cleanup list. 


cl_add_shared Add a shared allocated cell 
INT cl_add_shared (VOID *p); 

Add a shared allocated heap cell, with handle p, to the cleanup list. 

Calling this function is equivalent to calling: 


cl_add(TY_CLEANUP_SHARED, p) ; 


Returns an index number which identifies the newly added item in the cleanup list. 


The function may call p_leave (E_GEN_NOMEMOoRY) , but not until after the item has been added to the 
cleanup list. 


cl_add_dyl Add a DYL 
INT cl_add_dyl(VOID *p); 

Add a DYL, with handle p, to the cleanup list. 

Calling this function is equivalent to calling: 


cl_add (TY_CLEANUP_DYL, p) ; 


Returns an index number which identifies the newly added item in the cleanup list. 


The function may call p_leave (E_GEN_NOMEMOoRY) , but not until after the item has been added to the 
cleanup list. 


OLIB REFERENCE 


cl_remove Remove an item 


VOID cl_remove (INT num); 


Remove the item specified by num (as returned by an earlier cL_app message or a call to one of the cl_add 
convenience functions) from the cleanup list without cleaning up its associated resource(s). 


The item is removed by setting its type to Ty_cLEANuP_vorp. No memory is freed. 
Calling this function is equivalent to: 


p_send3 (w_am—>appman.clean, O_CL_REMOVE, num) ; 


cl_clean_item Delete an item 


VOID cl_clean_item(INT num); 


Clean up the resource(s) associated with item num (as returned by an earlier cL_app message or a call to 
one of the c1_add convenience functions) and remove the item from the cleanup list. 


No allocated memory associated with the cleanup list's array is freed but the item's type is set to 
TY_CLEANUP_vorp So that it is available for re-use. 


Calling this function is equivalent to: 


p_send3 (w_am—->appman.clean, O_CL_CLEAN_ITEM, num) ; 


CHAPTER 10 


THE APPMAN APPLICATION MANAGER CLASS 


APPMAN 


clean 
system 
rcb 
sxrcb 
ipcs 
task 
stop 
nrid 
err 
sparel 
spare2 


am_init 

am_start 

am_stop 
am_add_task 
am_wait 
am_load_resource 
am_load_res_buf 


am_rscname 


am_notify 


am_notifyerr 
am_clean_up 
am_onlyone 
am_findimg 


am_change_pri 


The main function of the application manager class appman is to provide an application's central logic for 
scheduling the processing of events which may derive from more than one source. As such, it is 
fundamental to the operation of a SIBO application, providing the basic support for a multi-threaded 
approach to the processing of events from different sources (such as keypresses, the receipt of data from a 
serial port and the expiry of timers). 


In addition, the application manager supplies some general utilities, including methods to access resources 
held in resource files, together with some basic error handling and notification services. 


An application process almost invariably creates an instance of the application manager or, more 
commonly, an instance of a user interface subclass of the application manager (for example, HwImman - see 
the HWIM Reference manual). This instance normally remains in existence for the lifetime of the 
application process. 


The reserved static w_am is intended to be used to store the handle of an application's application manager, 
making its methods accessible from any part of the application code. 


Each of the events that are scheduled by appman is represented by an active object, i.e. an instance of a 
subclass of active. The application manager maintains a queue, in priority order, of instances of active 
objects and the am_start method schedules processing between them in a non pre-emptive way. 


10-1 


OLIB REFERENCE 


For example, an application which is printing could have the following structure: 


Ys 


where the application manager (AM) holds a queue of three active objects, WS, PR and TI, representing: 
e the window server (WS) 
e aprinter channel (e.g. a serial port) (PR) 
e an asynchronous timer (TI) 


In this example, printing is performed by making a write request on the printer active object and a 
time-out request on the timer active object. (Note that, in general, there will also be an outstanding event 
read request on the window server active object.) 


The application manager waits for an event which, in this case, will be the completion of any one of the 
requests on the three active objects. When an event occurs, the application manager scans its active object 
queue to determine which active object has a completed request and is prepared to run. The application 
manager will then send an ao_RuN message to the appropriate active object. 


If, in our example, the printer write request completes, the printer active object will be sent an ao_RUN 
message. The printer's ao_run method will typically cancel the timer's time-out request and then repeat its 
own write request and the timer's time-out request, to continue printing. Alternatively, if the time-out 
expires, the timer active object will be sent an ao_RuN message. The timer's ao_run method will abandon 
printing by cancelling the write request on the printer active object. 


A window server read event may complete at any point in the printing process - for example, to redraw a 
window or to indicate loss of foreground. In this case the window server active object will receive an 
AO_RUN message and the processing of the window server event is automatically interleaved with the 
processing of the write and time-out events but note that the processing of a write or a timeout event 
cannot be interrupted to handle a window server event. 


Active object priorities 


The application manager's queue of active objects is maintained, and scanned, in priority order. The 
priority is a signed value, so that the default value of zero is in the middle of the range. The range of 
predefined priorities is given in the Active Objects chapter of this manual. 


If more than one active object has generated an event, the first task in the queue is given absolute priority 
- a task at the end of the queue only runs when all earlier tasks are not prepared to run. It is fundamental 
to the scheduling process to note that: 


e the events which signal the completion of requests do not necessarily occur in the order in which 
the requests were made 


e the active objects are not necessarily given an opportunity to run in the order of completion of the 
corresponding requests - if more than one request has completed, the scheduling mechanism will 
give the object with the highest priority the first opportunity to run. 


However, each active object which makes a request will, of course, eventually receive an invitation to run 
at some time following the completion of its request. 


Once the application manager has sent an ao_RUN message to an active object, no other active object can 
be given an opportunity to run until the processing of the ao_RuN message is complete and the ao_run 
method has returned. The application manager has no means of preempting the current active object 
(contrast this with the EPOC operating system in which scheduling is preemptive). If the processing of an 
event takes an extended time to perform, all sources of events are blocked for that period of time and this 
may reduce the perceived quality of the application. In particular, the processing of user input (seen as an 
event from the window server) is delayed - the application temporarily goes deaf. A technique for coping 
with this situation is discussed in the Idle Objects and the AIDLE Class chapter of this manual. 


10-2 


10 THE APPMAN APPLICATION MANAGER CLASS 


Active object scheduling 


APPMAN'S active object scheduling is a complex process, requiring close cooperation between appman and 
the active objects in its queue. During the process, appman reads and modifies property elements of the 
active objects. It is, therefore, not possible to discuss the scheduling process without making some 
reference to the behaviour of active objects. Perhaps the clearest approach is to consider what qualifies an 
active object to be offered a chance to run. 


The first requirement is that it must have made a request to be run, usually by execution of its ao_queue 
method. At this point it will have triggered a sequence which will eventually result in an event being 
detected by appman. appman detects an event by calling p_iowait which returns when p_iosignal is 
called.! The ao_queue method will normally trigger a p_iosignal by making an asynchronous request, 
during which the active.stat field is usually set to —_FILE_PENDING (but see the exception discussed 
below, under the heading The ao_run return value). The making of a request is indicated by the active 
object changing state, from inactive to active (the active.isactive field changes from FaLsE to TRUE). 


The later completion of the asynchronous request results in active.stat being set to a value other than 
E_FILE_PENDING. 


APpPMaN detects an event by the receipt of a signal on the I/O semaphore of its process. At this point the 
application manager scans, in priority order, all active objects in its queue. If, in the property of an active 
object, active.isactive is set to TRUE, the value of active.stat is examined. If this is set to any value 
other than &_FILE_PENDING the active object is assumed to be prepared to consume the event and is sent 
an AO_RUN message. Normally, the active object confirms that it has consumed the event (signal) by 
returning the value RUN_ACTIVE_USED (see below, under the heading The ao_run return value, for 
exceptions). 


If an active object confirms that it has consumed the event, the application manager scheduling loop waits 
for the next event, otherwise it continues looking for an active object that can consume the event. The fatal 
condition, known as stray signal death, occurs if the application manager reaches the end of its list before 
any active object consumes the event. In this situation the application manager calls 

p_panic (P_PANIC_APPMAN_1). (This panic has the value 143.) 


(For further details of asynchronous processes, see the Asynchronous Requests and Semaphores chapter in 
the PLIB Reference manual.) 


Note that appman reads an active object's active.isactive and active.stat property fields for reasons of 
efficiency. It avoids the duplication of the tests of these fields in the ao_run method of each active object 
and, more importantly, executes more efficiently since messages are not sent to active objects that are not 
prepared to run. 


The ao_run return value 


Normally, an active object will represent a source of events of a single type. According to the above 
description of the scheduling mechanism, the active object will not be sent an ao_Run message unless the 
corresponding asynchronous event has completed. In consequence, the ac_run method of such an active 
object can only ever return the value RUN_ACTIVE_USED. 


For largely historical reasons an ao_run method may return RUN_ACTIVE_UNUSED to indicate that it has not 
consumed the event. This could, for example, be of use where a single active object is used to represent 
two or more related event sources of different types, for example, serial port reads and writes. 


Such an active object would need to maintain a separate status word (in its property) for each type of 
asynchronous request, leaving active.stat with a permanent zero value. It would then be liable to 
receive an AO_RUN message at any time that active.isactive iS TRUE, regardless of the completion status 
of any of its outstanding asynchronous requests. The ao_run method should only return 
RUN_ACTIVE_UNUSED if none of its outstanding requests have completed. 


This technique, although relatively simple to implement, is inefficient if the application contains other 
active objects of equal or lower priority. In such a situation the active object will, in general, be sent a 
number of ‘unnecessary’ Ao_RUN messages. From an architectural point of view, and in the interests of 
efficient execution, it is better to implement the handling of multiple event sources by using a separate 
active object for each event source. Each active object will then only be sent an ao_RuN message when its 
corresponding outstanding request has completed (and will always return the value RUN_ACTIVE_USED). 


! The call to p_iosignal is thus the event source. 


10-3 


OLIB REFERENCE 


Precursors 

The reader is assumed to understand: 
e the PLIB/EPOC I/O system, waits, signals and semaphores. 
e the requirements of an event-driven system. 
e =the p_enter and p_leave error handling services. 


Class diagram 


“— 


/ — 
¢ appman 
¢ cleanup =. 
x ) 7 system / 
kg. gre 5 Sas es = ae 
(oa Se Se 
y tscfile / ¢ pes / 
~~ ) S _) 
i oe ae 


APPMAN may optionally reference (use) one or more of the CLEANUP, RSCFILE, IPcs and system classes. 
Class definition 
Defined in sub-category file appman.cl (generated header file appman.g). 


CLASS appman = root 


Application manager -— schedules attached active objects 
{ 
ADD am_init Initialise task queue 
ADD am_start Start a scheduling loop 
ADD am_stop Exit one level of the scheduling loop 
ADD am_add_task Insert active object into task queue 
ADD am_wait=p_iowait Wait for the next signal 
ADD am_load_resource Load a resource file record into memory 
ADD am_load_res_buf Load a resource file record into buf supplied 
ADD am_rscname Supply a resource file name at initialisation 
ADD am_notify Notify user 
ADD am_notifyerr Notify user of error 
ADD am_clean_up Clean all logged objects then do an abrun 
ADD am_onlyone Called when the only one check fails 
ADD am_findimg Re-find the image if the pack is moved 
ADD am_change_pri Change the priority of an active object 
CONSTANTS 
{ 
FLG_APPMAN_CLEAN Ox01 Create a cleanup list component 
FLG_APPMAN_ SYSTEM 0x02 Create a system configuration component 
FLG_APPMAN_RSCFILE 0x04 Create a resource file component 
FLG_APPMAN_SRSCFILE 0x08 Create a system resource file component 
FLG_APPMAN_IPCS Ox10 Create an ipcs component 
FLG_APPMAN_ONLYONE 0x20 Fail if same process already exists 
FLG_APPMAN_NODBG 0x40 Don't grope for dbg.dyl if set 
RUN_ACTIVE_UNUSED 0 Signal not used 
RUN_ACTIVE_USED 1 Signal used 
ERR_APPMAN_APPL =512 Base for application specific leaves 
} 
PROPERTY 5 
{ 
PR_CLEANUP *clean; cleanup list for leaves 
PR_SYSTEM *system; system configuration object 
PR_RSCFILE *rcb; application resource file 
PR_RSCFILE *srcb; system resource file 
PR_IPCS *ipcs; ipcs object 
P_QUE task; queue header 
UWORD stop; start level counter 
WORD nrid; context message rid for notify 
WORD err; abrun error 
UBYTE *sparel; Spare for future expansion. 
UBYTE *spare2; Spare for future expansion. 


} 


10-4 


Property 


appman. 


appman. 


appman. 


appman. 


appman. 


appman. 


appman. 


appman. 


appman. 


appman. 
appman. 


clean 


system 


rcb 


sxrcb 


ipcs 


task 


stop 


nrid 


err 


sparel 
spare2 


10 THE APPMAN APPLICATION MANAGER CLASS 


Contains the handle of the created cLzanup object if the 
FLG_APPMAN_CLEAN flag was specified to am_init. The cLzanup object 
handle is used when an active object's ac_run method leaves with error. 
All applications will normally create a cLEanup object. This field should 
be treated as read only by all objects. 


Contains the handle of the created system configuration object if the 
FLG_APPMAN_SYSTEM flag was specified to am_init. This field should be 
treated as read only by all objects. 


Contains the handle of the created application resource file Rscr ILE object 
if the FLG_APPMAN_RSCFILE flag was specified to am_init. This object is 
used in the am_load_resource and am_load_res_buf methods, provided 
the specified resource id is positive. This field should be treated as read 
only by all objects. Note that rscriLe objects require the use of the 
application manager's cLEANUP object. 


Contains the handle of the created system resource file Rscr1LE object if 
the FLG_APPMAN_SRSCFILE flag was specified to am_init. This object is 
used in am_load_resource and am_load_res_buf methods if the specified 
resource id is negative. This field should be treated as read only by all 
objects. Note that rscrILE objects require the use of the application 
manager's CLEANUP object. 


Contains the handle of the created 1pcs object if the rLG_APPMAN_IPCS 
flag was specified to am_init. This field should be treated as read only by 
all objects. 


This is the head of the active object task queue. All active objects are 
inserted into this queue when they send the application manager an 
AM_ADD_TASK message. The queue is maintained in priority order. Note 
that if an active object wishes to change its priority it should send appman 
an AM_CHANGE_PRI message; just changing the priority property field is 
not sufficient. This field should not be accessed by any subclass. 


Maintains the current level of active object event scheduling, as set by the 
am_start and am_stop methods. This field should not be accessed by any 
subclass. 


This field is intended to be used by applications to store a resource id to be 
used in reporting errors. The idea is that this resource id changes as the 
execution of code progresses, the id providing a context of where the 
error(s) are occurring. appMan makes no use of this variable itself, but it is 
used by ACTIVE’s ao_abrun method. 


Contains the error returned by the ao_run method of an object. The error 
number is placed there by the am_clean_up code before the ao_abrun 
method is called. This allows the error to be more accessible than if it 
were just passed as a parameter, and also reduces stack build up. 


Reserved for future expansion. 


APPMAN Methods 
AM_INIT 


VOID am_init (UINT flags); 


Initialise 


Initialise the task queue and create a series of objects as determined by flags which should contain a 
combination of the flag values listed below. 


If an error is encountered during initialisation p_1leave is called with the appropriate error. If the 
initialisation fails, an application must assume that none of the requested objects have been created. In 
particular, no resource files will have been opened and hence the application can only exit, without 
attempting to use any resource data. 


10-5 


OLIB REFERENCE 


The following descriptions of the various flag values make reference to a number of other object classes. 
For more information on any of these classes, see the appropriate section of this manual. 


FLG_APPMAN_CLEAN 


FLG_APPMAN_SYSTEM 


FLG_APPMAN_RSCFILE 


FLG_APPMAN_SRSCFILE 


FLG_APPMAN_IPCS 


FLG_APPMAN_ONLYONE 


FLG_APPMAN_NODBG 


© AM_WAIT 


VOID am_wait (VOID) 


This flag causes an instance of the cLEanup class to be created and initialised 
with a granularity of 8. This is used to lodge items that must be 'cleaned up' 
on error. 


This flag causes an instance of the system class to be created and initialised 
(see the System Services chapter). This is used to obtain system-wide 
information. 


This flag causes an instance of the rscFILE class to be created to provide 
access to the application resource file (see the Resource Files chapter). The 
name of the resource file is generated by the am_rscname method, which 
should be subclassed if a different name is required. Note that the rscriLE 
class requires the presence of an instance of the cLzanup class, so this flag 
must always be accompanied by rLG_APPMAN_CLEAN. 


This flag causes an instance of the rscFrILz class to be created, to provide 
access to the system resource file (see the Resource Files chapter). Note that 
the rscri1Le class requires the presence of an instance of the cLEanup class, 
so this flag must always be accompanied by rLG_APPMAN_CLEAN. 


This flag causes an instance of the 1pcs class to be created and initialised 
with a maximum message size of 8 bytes, in a queue of length 4 (see the 
Inter-process Communication chapter). If this is insufficient then the 
application should not use this flag, but should explicitly create its own 1pcs 
object. 


This flag should be set if there must be only one process of this type running 
at any one time. It is, for example, set for Alarms, Link and the System 
process. 


If this flag is set and another process exists with the same name as the one 
now being run, appman sends itself an am_ONLYONE message, passing the 
process id of the other process. 


In the absence of Psion's internal test and debug library, dbg.dyl, this flag 
has no effect. If this flag is clear and dbg.dy1 is present in the appropriate 
directory, a debug object is created to run test procedures and display various 
items of debug information for the application. 


Wait on I/O semaphore 


Waits on the I/O semaphore by calling p_iowait. 


When an event occurs, it signals the I/O semaphore which causes p_iowait, and hence am_wait, to return. 


AM_START 


VOID am_start (VOID) 


Start scheduler 


Start a new level of the application manager active object event scheduler. This method normally does not 
return until the application manager receives an AM_STOP message. 


The code of this method is presented below, since it is crucial to the understanding of the application 
manager's active object scheduling mechanism. 


10 - 6 


10 THE APPMAN APPLICATION MANAGER CLASS 


LOCAL_C RunTask(FAST PR_ACTIVE *htask) 


{ 
INT ret; 


htask->active.isactive=FALSE; 

ret=p_send2 (htask,O_AO_RUN) ; 

if (ret==RUN_ACTIVE_UNUSED) 
htask->active.isactive=TRUE; 

return (ret); 


} 


LOCAL_C RunCleanupAbrun(PR_APPMAN *self,INT err,VOID *htask) 
/* 
Enterable shell 
e/. 
{ 
p_send4 (self,O_AM_CLEAN_UP,err,htask) ; 
return (0); 


} 


METHOD VOID appman_am_start (PR_APPMAN *self) 
/* 
Start the basic loop to get a message from the server. 
May be called recursively for modal interaction. 
%/ 
{ 
INT stop, ret, abret; 
FAST P_QUE *pt; 
FAST PR_ACTIVE *htask; 


stop=(++self-—>appman.stop); 
if (self->appman.clean) 
p_send3 (self-—>appman.clean, O_CL_SET_LEVEL, stop) ; 
do 
{ 
p_send2(self,O_AM WAIT); /* wait for next event */ 
for (pt=self->appman.task.next;;pt=pt—>next) 
{ /* find a task to run */ 
if (pt==&self—>appman.task) 
p_panic(P_PANIC_P_APPMAN_1); /* stray signal */ 
htask=(PR_ACTIVE *) (((UBYTE *)pt)-sizeof(PR_ROOT) ); 
if (htask->active.isactive && htask->active.stat!=E_FILE_PENDING) 
{ 
abret=0; 
if ((ret=p_enter2 (RunTask,htask))<0) /* p_leave(err) called */ 
{ 
abret=p_enter4 (RunCleanupAbrun, self, ret, htask) ; 
if (abret) 
self-—>appman.stop-—; 


} 
if (ret !=RUN_ACTIVE_UNUSED) 
break; 


} 
} while (self-—>appman.stop==stop) ; 
if (self->appman.clean) 
{ 
p_send2 (self-—>appman.clean, O_CL_CLEAN_LEVEL) ; 
p_send3 (self-—>appman.clean, O_CL_SET_LEVEL, stop-1) ; 
} 
if (abret) 
p_leave(abret); /* allow +ve 'errors' */ 


} 


On entry, appman. stop is incremented. Provided appman.clean is non-zero, the cLEANUP object is sent a 
CL_SET_LEVEL message to set its level to the new value of appman. stop. 


The scheduler waits for an event by sending itself an am_wart message. On return, all objects that are 
currently active (active.isactive Set to TRUE) have their completion status words (active.stat) 
checked. If the completion status word is not E_FILE_PENDING the object is sent an ao_RUN message. 


10-7 


OLIB REFERENCE 


Assuming that there are no errors, if the object does not consume the event it must return 
RUN_ACTIVE_UNUSED, Otherwise it returns any other value, normally returning RUN_ACTIVE_USED. 


If the list of active objects is exhausted without the event being consumed, the scheduling loop calls 
p_panic (P_PANIC_APPMAN_1), indicating the stray signal death condition. 


Before sending the ao_run message, the application manager sets the active object's active.isactive to 
FALSE. If the object returns RUN_ACTIVE_UNUSED, active.isactive Is set back to TRUE since the object 
must still be left in the active state if it does not consume the event. If the active object leaves with an 
error, as described below, the TRuz value is not written to active.isactive. (Note that changing the value 
of active.isactive is a code-saving service, avoiding the duplication of code in each active object.) 


Any error in the ao_run method is expected to result in p_leave being called. The ao_Run message is sent 
under the protection of a p_enter which catches any p_leave error calls. If an active object calls p_1eave 
within its ac_run method the application manager will receive an error (negative) return value and will 
then send an am_cLEAN_UP message, passing the error that was detected and the handle of the active object 
that called p_ieave. 


The am_cLEAN_upP message is also sent under the protection of a p_enter and any non-zero return value 
(representing a p_leave exception in the error handling code) is stored for later use. Note that this will 
cause the current level of event scheduling to terminate, with the error being propagated to the previous 
level. The technique of calling p_1eave within the error handling code should therefore only be used with 
extreme caution. 


Note that an ao_run method is free to terminate its processing prematurely by calling p_leave with a zero 
or positive argument - a preferred form of the call is p_leave (RUN_ACTIVE_USED). Such termination will 
not trigger the error reporting and recovery mechanism and may be considered equivalent to a normal 
termination that returns RUN_ACTIVE_USED. 


Once an object consumes the signal, by returning a value other than RUN_ACTIVE_UNUSED from its ao_run 
method, no more objects are polled. At this point the am_start method normally loops back to send itself 
another am_wAIT message to wait for the next event. 


The exceptions to this are: 
e if an active object has sent an aM_sTop message in its ao_run method 
e if a non-zero return value resulted from the am_cLEAN_UP message. 


In either case appman. stop will have been decremented. On completion of the processing of the current 
event, the am_sTart method returns, exiting one level of scheduling. 


Before returning, the application manager's cLEaNuP object (if it exists) is sent a CL_CLEAN_LEVEL 
message, to discard all items still in the cleanup list at the current level. It is then sent a cL_SET_LEVEL 
message to adjust it to the new (lower) scheduling level. If a non-zero value resulted from the 
AM_CLEAN_UP message, p_leave Is called, passing this value, to propagate the exception generated in the 
error handling code to the previous level of scheduling. 


The application manager active object event scheduler is re-entrant. Thus the ao_run method of an active 
object can send the application manager an aM_sTART message to enter a further level of scheduling. 
Normally, the active object which sends the am_start message will, at that time, have active.isactive 
set to FALSE (by the application manager, before it sends the ao_RuN message) and will therefore not 
receive any further ao_ruN messages until an amM_sTop message is sent. Events occurring under other 
active objects in the application manager's queue will, however, continue to be processed as normal. An 
important example of such use is when a modal dialog box is being run from a menu selection. 


There is a great temptation to use this technique to implement any synchronous sequence of actions by 
means of an active object whose initialisation method, say, sends an ao_QuEUE message and then sends the 
application manager an am_sTart message. This technique should be used with care, particularly when 
recovery from an error involves items on the cleanup list. 


Because of the different level, the items that are cleaned will be different for an error that occurs before an 
AM_START message (for example, during an initialisation phase) from the items that are cleaned up after 
(say, within an ao_run method). It may be advisable to transfer any part of the initialisation that can fail 
into an ao_run method and execute it under the control of a state variable in the object's property, the first 
time that the ao_run method is called. This also resolves any problem as to whether the error recovery 
code should or should not send an am_stop message. The following general code briefly illustrates the 
principle of implementing such an active object sequencer: 


10-8 


10 THE APPMAN APPLICATION MANAGER CLASS 


GLREF_D PR_APPMAN *w_am; 


VOID sequence_ao_init (PR_SEQUENCE *self) 
{ 
self—>active.priority=PRIORITY_ACTIVE_COMPUTE; 
p_send3 (w_am, O_AM_ADD_TASK, self) ; 
self—>active.isactive=TRUE; 


p_iosignal(); 
p_send2 (w_am,O_AM_START) ; 
} 


sequence_ao_run(PR_SEQUENCE *self) 
{ 
switch (self-—>sequence.state_variable) 
{ 
case 0: 
/* initialise */ 
break; 
case 1: 
/* action 1 */ 
break; 
case 2: 


case 5: 
p_send2 (w_am,O_AM_STOP) ; 
return (RUN_ACTIVE_USED) ; 
} 


self—>sequence.state_variablet=1; 


self—->active.isactive=TRUE; 
p_iosignal(); 

return (RUN_ACTIVE_USED) ; 

} 


& AM _STOP Stop scheduler 


VOID am_stop (VOID) 


Stop the current level of the active object event scheduling loop, by decrementing appman. stop. This 
causes the most nested am_start to return after handling of the current event is complete. 


& AM_ADD_TASK Add a task 


VOID am_add_task(PR_ACTIVE *hand) ; 


Add an initialised active object to the task queue, in priority order, as determined by the active object's 
active.priority field. 


The item is added to the list immediately following all existing items with the same (or higher) priority. 


AM_LOAD_ RESOURCE Load a resource 


INT am_load_resource(INT resid, UBYTE **ppdata) ; 
Allocate a buffer and load into it the resource with id resia from the appropriate resource file. 


A negative resid indicates that the resource is to be found in the system resource file, with an id equal to 
the absolute value of resid. Otherwise it is assumed that the resource is to be found in the application 
resource file. 


If you wish to access the system resource file you must have passed the FLG_APPMAN_SRSCFILE flag to the 
am_init method. It is recommended, but not strictly essential (because the am_load_resource method will 
search for and open the application resource file if it is not already open) that you pass the 
FLG_APPMAN_RSCFILE flag to the am_init method if you wish to access the application resource file. 


If the appropriate rscFILE object exists, the resource is loaded by sending an rs_READ message to the 
appropriate RSCFILE object, under the protection of p_enter. If the loading of the resource fails due to out 
of memory then p_leave (E_GEN_NoMEmoRY) is called. 


10-9 


OLIB REFERENCE 


Any other error when attempting to read an application resource, including the absence of the application 
resource RSCFILE object, is assumed to be due to the removal of the application resource file. (It is 
assumed that only the application resource file can be removed since the system resource file is in the 
ROM.) If the application manager's application RscrILE component exists, it is destroyed. An attempt is 
then made to locate the resource file by sending am_Finp1mc and am_RscnameE messages. If this is 
successful the RscFILE object is recreated and the file reopened - either of which could fail, calling 
p_leave (E_GEN_NOMEMoRY) - otherwise the method calls p_1eave (Z_FILE_NXIST) . Following this, the 
resource is loaded by sending the appropriate rscrILz object an RS_READ message, which may fail - 
typically by calling p_leave (E_GEN_NOMEMORY) . 


The method returns the size of the loaded resource, as returned by the rs_READ message. 


AM_LOAD_RES_ BUF Load a resource to a buffer 


INT am_load_res_buf (INT resid, UBYTE *pbuf) ; 
Load into the buffer pointed to by pbut the resource with id resia from the appropriate resource file. 


A negative resid indicates that the resource is to be found in the system resource file, with an id equal to 
the absolute value of resid. Otherwise it is assumed that the resource is to be found in the application 
resource file. 


If you wish to access the system resource file you must have passed the FLG_APPMAN_SRSCFILE flag to the 
am_init method. It is recommended, but not strictly essential (because the am_load_resource method will 
search for and open the application resource file if it is not already open) that you pass the 
FLG_APPMAN_RSCFILE flag to the am_init method if you wish to access the application resource file. 


If the appropriate RscFILE object exists, the resource is loaded by sending an rs_READ message to the 
appropriate RSCFILE object, under the protection of p_enter. If the loading of the resource fails due to out 
of memory then p_leave (E_GEN_NoMEMoRY) is called. 


Any other error when attempting to read an application resource, including the absence of the application 
resource RSCFILE object, is assumed to be due to the removal of the application resource file. (It is 
assumed that only the application resource file can be removed since the system resource file is in the 
ROM.) If the application manager's application RscrILE component exists, it is destroyed. An attempt is 
then made to locate the resource file by sending am_F1npIMc and am_RscnamE messages. If this is 
successful the RscFILE object is recreated and the file reopened - either of which could fail, calling 
p_leave (E_GEN_NOMEMORY) - otherwise the method calls p_1leave (Z_FILE_NXIST) . Following this, the 
resource is loaded by sending the appropriate rscFrILz object an RS_READ message, which may fail - 
typically by calling p_leave (E_GEN_NOMEMORY) . 


The method returns the size of the loaded resource, as returned by the rs_READ_BUF Message. 


AM_RSCNAME Generate resource file name 


VOID am_rscname(UBYTE *pname) ; 


Write to the buffer at *pname (which must be at least p_rnames1zeE bytes long) the default full file 
specification (see the Files chapter of the PLIB Reference manual) of the application resource file. 


The name is generated from the application's start-up full file specification, pointed to by the magic static 
DatCommandPtr. 


The resource file is assumed to be built into the image file, so that the full file specification is identical to 
that of the image file. 


& AM_NOTIFY Display notifier 


VOID am_notify(UINT messl, UINT mess2, UWORD *pbut) ; 
Call the p_notify service with text loaded from resource files. 


Up to two text messages are specified by the resource ids mess1 and mess2. If pbut is Nutt, the single 
default button 'CONTINUE' (or the non-English equivalent) will be displayed. Otherwise, pbut is 
assumed to point to an array of three resource ids for the three notifier buttons. 


All resource ids follow the resource id rules as specified in the description of the am_load_resource 
method. If any id is nunz then no text is loaded for that id. 


10 - 10 


10 THE APPMAN APPLICATION MANAGER CLASS 


Once the resource strings are loaded the p_not ify service is invoked. The allocated space for the resource 
strings is freed after use. 


This method will not fail due to lack of memory. If there is not enough memory available to load any of 
the specified resources, the corresponding part of the notification text is not displayed. 


& AM_NOTIFYERR Notify an error 


VOID am_notifyerr(INT err, UINT messl1,UWORD *pbut) ; 
Call the p_notifyerr service, with text loaded from resource files. 


A first line text message is specified by the resource id messi. A second line contains a description of the 
error, as generated by p_errs (err). If pbut is nuLt, the single default button 'CONTINUE' (or the non- 
English equivalent) will be displayed. Otherwise, pbut is assumed to point to an array of three resource 
ids for the three notifier buttons. 


All resource ids follow the resource id rules as specified in the description of the am_load_resource 
method. If any id is nunz then no text is loaded for that id. 


Once the resource strings are loaded the p_notifyerr service is invoked, which converts the error number 
err into the second line text message. The allocated space for the resource strings is freed after use. 


This method will not fail due to lack of memory. If there is not enough memory available to load any of 
the specified resources, the corresponding part of the notification text is not displayed. 


AM_CLEAN_UP Clean up resources and report an error 


VOID am_clean_up(INT err, UBYTE *htask); 
Provide standard error recovery and reporting for the active object event scheduler. 


This method is called from the am_start event scheduler if an active object's ac_run method calls 
p_leave (error). The handle of the active object is in htask and err is the error number passed to 
p_leave. 


The value of err is copied to appman.err and if there is a cLEaNupP object it is sent a CL_CLEAN_LEVEL 
message to tidy up all resources added to the cleanup list at this level of event scheduling. 


If htask is not NULL, AN AO_ABRUN message Is sent to that object. The ao_abrun method may call p_leave, 
in which case the error will be caught in the am_start method. It will cause the current level event 
scheduling to terminate, the p_leave error being propagated to the next level of scheduling. 


This method is supplied in order to facilitate the customising of all, or a particular set of, errors. 


Note that the active object which generated the error in its ao_run method is sent an Ao_ABRUN message 
after the sending of the cL_cLEAN_LEVEL message. This means that (unless the am_cleanup method is 
subclassed) the active object must not itself be in the cleanup list at the current level, otherwise it will be 
destroyed before the ao_aBrun message is sent. It is likely, in any practical case, that an active object that 
has been placed in the cleanup list will have been removed before it receives its first ao_RUN Message. 


In general, the active object will only be placed in the cleanup list temporarily while other objects are 
being built and resources acquired; in this state of construction, it is unlikely that an application would 
"activate" the active object and risk receiving an Ao_ABRUN Message. 


AM_FINDIMG Find application image file 


INT am_findimg (VOID) ; 
Relocate the SSD from which the application was run. 


It uses the magic static DatCommandPtr, assuming that it points to the current full file specification of the 
application's .img (or .app) file. It looks in all available SSD drives (A and B and, if they exist, C and D). 
If it finds a file with the same name in the directory specified by pat commandPtr it patches the data at 
DatCommandPtr to reflect the new path and returns zero. If no such file can be found £_F1LE_nxist (the 
return value from a p_finfo call) is returned. 


Typically this is called when the application wishes to access some information from the SSD from which 
it was run, but finds that the SSD is no longer in that drive. It is used in this way by the 
am_load_resource and am_load_res_buf methods. 


10-11 


OLIB REFERENCE 


AM_ONLYONE Ensure only one copy running 
VOID am_onlyone(UINT pid); 


Ensure that a second copy of an application is not launched. This method simply calls 
p_leave (E_FILE_EXIST). 


It is called during the am_init method if the rLc_appMaN_oNLyYonE flag was specified and another process 
of the same name is already running. 


The Alarm application is an example of a process which should never have more than one copy running. 


& AM_CHANGE_PRI Change active object priority 


VOID am_change_pri(PR_ACTIVE *pObject, INT priority); 


Change the priority of the active object with handle pobject to the value in priority. 


The result will be unpredictable if the object is not currently in the application manager's active object 
queue. 


The active object is removed from the application manager's active object queue, the new priority is copied 
into active.priority and the object is then re-inserted with the new priority. 


10-12 


CHAPTER 11 


THE ACTIVE CLASS AND ACTIVE OBJECTS 


ACTIVE 


gq 
priority 


isactive 
pcb 
stat 


destroy 
ao_init 
ao_cancel 
ao_abrun 
ao_queue 


ao_run 


The active class provides common behaviour for active objects. An active object may be thought of as an 
event source and is, by definition, any object which has acTIVE as an ancestor in its inheritance tree. 


Active objects are fundamental to the operation of event-driven SIBO applications (the overwhelming 
majority of all SIBO applications). In such an application, virtually all processing is performed within the 
ao_run method of some active object or other. 


Although it is not formally an abstract class, the acTIveE class must be subclassed to create a useful active 
object. OLIB and HWIM supply a number of subclasses of active for use by applications. In addition, an 
application may define one or more application-specific active object classes. 


A typical active object corresponds to an asynchronous channel on one of PLIB's I/O devices. An 
assumption, embodied in acTIve's property, is that only one asynchronous event per active object can be 
outstanding at any one time. 


See the Application Manager chapter for further information about active objects and event scheduling. 


Note that active objects making asynchronous requests on the file server should subclass FAcTIVE in 
preference to active. See the File Active Objects chapter for further details. 


Precursors 


The reader is assumed to understand: 
e the appman class, in particular the event scheduling mechanisms. 
e the PLIB/EPOC asynchronous I/O system, waits, signals and semaphores. 
e requirements of an event-driven system. 


e =the p_enter and p_leave error handling services. 


11-1 


OLIB REFERENCE 


Class definition 


The actrve class subclasses root and is defined in the sub-category file appman.cl (with generated header 
file appman.g). 


CLASS active root 
Active object superclass for representing event sources 


{ 


REPLACE destroy Close IO channel and free itself 
ADD ao_init Open IO channel 
ADD ao_cancel Cancel outstanding read request 
ADD ao_abrun Abnormal, p_leave induced, termination of ao_run 
ADD ao_queue Queue request (normally subclassed) 
ADD ao_run Provide an opportunity to run 
CONSTANTS 
{ 
! Priorities 
PRIORITY_ACTIVE_POSTER 100 
PRIORITY_ACTIVE_IPCS 80 
PRIORITY_ACTIVE_VOICE 70 
PRIORITY_ACTIVE_WSERV 60 
PRIORITY_ACTIVE_COMMAND 40 
PRIORITY_ACTIVE_SERIAL 20 
PRIORITY_ACTIVE_ALARM 0 
PRIORITY_ACTIVE_FILES -20 
PRIORITY_ACTIVE_REPEATER -40 
PRIORITY_ACTIVE_PRINT -60 
PRIORITY_ACTIVE_COMPUTE -100 
} 
PROPERTY 
{ 
P_QUE q; queue header 
BYTE priority; priority compared to other active objects 
UBYTE isactive; TRUE if there is a request pending 
UBYTE *pcb; I/O channel 
WORD stat; I/O completion status 
} 
} 
Property 
active.g Used by the application manager to include an active object in its 
prioritised queue. It should not be accessed other than by the application 
manager and an active object's destroy method. 
active.priority Used to determine the object's position in the application manager's 
prioritised queue. The value, which will normally be one of the priorities 
listed in the acttve class definition, should be set up prior to sending the 
application manager an aM_ADD_TASK message. 
active.isactive Should be set to TRuE when the active object is (or will be, on completion 
of an outstanding asynchronous request - see also active.stat) prepared 
to receive an Ao_RUN message. A common error is to fail to set 
active.isactive to TRUE when an asynchronous request is made. This 
will eventually cause stray signal death, described in the Application 
Manager chapter of this manual. The application manager sets 
active.isactive to FALSE when it sends the ao_RUN message, avoiding 
the need for the ao_run method of each individual active object to clear 
this field. 
active.pcb Normally holds the handle of the device upon which the active object 
makes its I/O requests. Many of the methods supplied by the actrve class 
assume that this is a true I/O channel handle. 
active.stat Normally used as the completion status word for an asynchronous request. 


Only if its value is not =_FILE_PENDING will the application manager's 
event scheduling loop send an ao_Run message to this active object 
(active.isactive must also be TRUE). 


11-2 


11 THE ACTIVE CLASSS AND ACTIVE OBJECTS 


ACTIVE methods 


J DESTROY Destroy the instance 


VOID destroy (VOID) 

Takes the following actions: 
e sends itself an ao_caNcEL message to cancel any pending asynchronous request 
e removes itself, if necessary, from the application manager's task queue 


e closes any I/O channel, whose handle is assumed to be in active.pcb (this is harmless if 
active.pcb is NULL) 


e supersends itself a pEsTRoy message. 


If a subclass uses active.pcb to contain anything other than an I/O channel handle, it should ensure that 
active.pcb 1s set to nuLL before this method is executed. 


AO_INIT Initialise the instance 
VOID ao_init (TEXT *devname, INT mode) ; 
Initialise the active object. 


Uses p_open to open a channel to the device specified by devname and mode, writing the channel handle to 
active.pcb. Calls p_leave if there is an error opening the channel. 


The object is not added to the application manager's task queue and no other fields in the property are 
changed. 


J AO_QUEUE Make a request to run 


VOID ao_queue (VOID) ; 


Set active.isactive to TRUE and signal the I/O semaphore by calling p_iosigna1 without altering the 
value of active.stat (whose default value is zero). As a result, the object will eventually be sent an 
AO_RUN message by the application manager. 


This method is provided for use by idle object subclasses (see Idle Objects and the AIDLE Class). Other 
active objects would normally subclass this method. All subclasses must ensure that the ao_queue method 
sets active.isactive tO TRUE. 


J AO CANCEL Cancel a request to run 


VOID ao_cancel (VOID) 
Cancel any outstanding asynchronous request. 
Does nothing if active.isactive is not TRUE. 


If active.isactive iS TRUE then it is re-set to FALSE. If active.pcb 1S not NULL, it is assumed to be the 
handle of an I/O channel and a p_FcancEL request is made to that channel. Regardless of the value of 
active.pcb, this is followed by a p_waitstat, waiting on active.stat. 


The ao_caNcEL message may be received before or after the corresponding request has completed: 


e if it is before the completion, the outstanding request is cancelled and the p_waitstat waits for, 
and absorbs the event which signals the completion of the cancel 


e if itis after the completion (but before its processing) the p_rcancEL request does not generate its 
own completion event. In this case the p_waitstat consumes the event already generated by the 
completion of the asynchronous request, effectively discarding it. 


Note that the completion result placed in active.stat 1s likely to be different in the above two cases, but 
is normally ignored since the status following a cancel is generally not significant. 


11-3 


OLIB REFERENCE 


Since the destroy method sends an ao_caNncEL message, the active class contains implicit assumptions 
that: 


e = the ao_cance1 method will never call p_leave 


¢ itis safe to send an ao_caNcEL message at any time, even if there has not been a previous 
AO_QUEUE Message. 


These assumptions about the cancel service are certainly true at the PLIB level, where a p_rcanceL does 
not rely on there being an outstanding request (for example P_FREAD or P_FWRITE). They are also true for 
all system-supplied subclasses of active. Subclassers of the active class should ensure that this 
assumption remains true. 


Active objects that perform operations on files should subclass ractive (described in the File Active 
Objects chapter) which provides the correct support for a file system cancel service. 


The ao_cance1 method provided by active may safely be used by non-I/O subclasses provided they leave 
active.stat at NULL. 


AO_ABRUN Handle an error 


VOID ao_abrun (VOID); 
Report an error condition arising from a call to p_leave in the object's ao_run method. 
Sends the application manager an aM_NOTIFYERR message: 


p_send5 (w_am, O_AM_NOTIFYERR, w_am->appman.err,w_am—>appman.nrid, NULL) ; 


and then sets appman.nrid tO NULL. 


The application manager has previously set appman.err to contain the error number passed as the 


parameter to p_leave, and appman.nrid 1s assumed to be either nut, or an application-specific resource 
id. 


The application manager and its property are accessed via the magic static w_am, which is assumed to 
have been initialised (as it is, for example, in the am_init method of the swimman subclass of appman - see 
the HWIM Reference manual). 


The ao_aprun method may be subclassed to provide more specific error handling. Note that a 
CL_CLEAN_LEVEL message will have been sent to any application manager cLEaNnup object before the 
AO_ABRUN message is received. 


AO_RUN Process an event 


INT ao_run (VOID) 


A default method which simply returns RuN_ACTIVE_USED, to signal to the application manager that it has 
consumed an event. Most active objects will subclass this method. 


An active object will only receive an ao_Run message if active.isactive iS TRUE and active.stat is not 
E_FILE_PENDING. The application manager sets active.isactive to FALSE before sending the ao_RuUN 
message. 


11-4 


CHAPTER 12 


IDLE OBJECTS AND THE AIDLE CLASS 


Idle objects 


Well-behaved applications should break down long, computationally intensive operations into a sequence 
of smaller sections processed in idle time, so that the application can avoid going deaf to window server 
messages for long periods of time. In other words, these operations should only be allowed to run when no 
other higher priority work is ready to run (e.g. responding to window server messages). 


This is normally achieved by using an active object of low priority (usually PRIORITY_ACTIVE_COMPUTE) 
which will only be run when no other active objects have any work to perform. An active object used for 
such a purpose is known as an idle object. 


An idle object will typically leave active.stat at a zero value and use the default ac_queue method 
provided by the active class. Its ao_run method is usually subclassed to perform a unit of processing and 
then (provided processing is not yet complete) send itself an ao_QUEUE message. 


A partially complete operation may be invalidated by a subsequent event. In such a case the operation 
should be cancelled and restarted. Such use of an idle object is appropriate, for example: 


in a text processor word wrapping a line at a time without falling behind in echoing user 
input in the current line. 


in a spreadsheet calculating a cell at a time in auto-calculate mode, allowing the user to 
continue to input during the calculation. 


An empty idle object - one whose ao_run method does nothing but send itself an ao_QUEVE message - will 
execute its ao_run method several hundred times per second. 


AIDLE 


ACTIVE 


gq 
priority 


isactive 
pcb 
stat 


destroy 
in 
ao_cancel 
ao_abrun 
ao_queue 


aeTFuFn 


The arpte class provides the basic functionality of an idle object. 


12-1 


OLIB REFERENCE 


The supplied ac_run method simply requests the application manager to exit from one level of application 
manager event scheduling by sending the application manager an am_stop message. In this form it may be 
used to pause some operation to allow the processing of other events. This usage, which is illustrated in 
the first example below, can be considered as a means of adding some aspects of idle time processing to 
code which, for one reason or another, is not suitable for implementation as an active object. 


A true idle object must subclass the ao_run method to perform the required processing, as described 
above, and as illustrated in the second example. 


Precursors 


The reader is assumed to understand: 
e =the active class 
e the application manager's event scheduling mechanism 


Class diagram 


fe 
(active / 
= ) 
CoS 


— 
— 


/ aidle / 
ie ) 


Nee 
Class definition 


Defined in sub-category file appman.cl (generated header file appman.g). 


CLASS aidle active 
Idle active object. 


{ 


REPLACE ao_init Add itself to active list at low priority 
REPLACE ao_run Send w_am an O_AM_STOP 
} 

Property 


None. 


AIDLE methods 


J AO_INIT Initialise 


VOID ao_init (VOID) 


Set active.priority tO PRIORITY_ACTIVE_COMPUTE and send the application manager an aM_ADD_TASK 
message. 


J AO RUN Run 


INT ao_run(VOID) ; 


Send the application manager an am_stop message and return RUN_ACTIVE_USED. 


12-2 


12 IDLE OBJECTS AND THE AIDLE CLASS 


Ds A nnn _______yz. 
Examples 


Pause an operation 


Some operations are not suitable for implementation in an active object format. The quicksort algorithm, 
for example, is recursive and therefore dependent on stacked state information. Since it could take an 
extended time to sort the data, some action should be taken to ensure that the calling application remains 
responsive to redraws and user input. A considerable rewrite would, however, be necessary to enable 
quicksort to execute as a sequence of separate calls to an ao_run method. 


A more convenient solution in such a case is to insert, at some point which is repeatedly executed, code 
which pauses execution and allows other events (such as redraws) to be processed. The principle is 
illustrated in the following code: 


VOID MakeIdle (VOID) 
{ 
INT i; 
VOID *aidle; 


aidle=f_newsend (CAT_DEMO_OLIB, C_AIDLE, O_AO_INIT); 
for (i=0;i<1000;i++) 
{ 


p_send2 (aidle, 0O_AO_QUEUE) ; 
p_send2 (w_am,O_AM_START); /* does not return until AIDLE has run */ 


} 
p_send2 (aidle,O_DESTROY) ; 


} 


The ao_quruz message is handled at the active level, simply setting active.isactive to TRUE and 
signalling the I/O semaphore. The send of the am_start message will not return until the am_stop 
message is sent by arpLE's ao_run method (which will not run until there are no outstanding events for 
any active object of priority higher than that of arp1z). 


Depending on the nature of the process, it may be more appropriate to pause, say, every tenth, or 
hundredth, time round the loop. In other words, it is the responsibility of the process to decide when or 
how often to pause. 


Idle time computation 


This example illustrates one of the most common forms of idle active object. It is the form that would be 
used, say, to reformat a portion of text, following the insertion or deletion of characters. It includes the 
ability to cancel and restart the operation on receipt of a further event (for example, another keypress) 
which invalidates a partially complete operation. 


Note that the ao_run method is subclassed so that no use is made of the functionality of arDLE's ao_run 
method. 


CLASS exidle aidle 
example idle object 


{ 


REPLACE ao_cancel to reset the processing state 
REPLACE ao_run perform a unit of processing 
PROPERTY 

{ 

WORD counter; records the current processing state 


} 
} 


METHOD VOID exidle_ao_cancel (PR_EXIDLE *self) 
{ 


self—>exidle.counter=0; 
p_supersend2 (self,O_AO_CANCEL) ; 
} 


12-3 


OLIB REFERENCE 


METHOD INT exidle_ao_run(PR_EXIDLE *self) 
{ 
p_printf ("Processing stage %d",self->exidle.counter+t+) ; 
if (self->exidle.counter<3) 
p_send2 (self, O_AO_QUEUE) ; 
return (RUN_ACTIVE USED); 
} 


The active object is run as illustrated below, following the action (say, the insertion of a character) which 
necessitates the processing. 


GLREF_D PR_EXIDLE *exidle; 


p_send2 (exidle,O_AO_CANCEL); /* cancel any partially complete processing */ 
p_send2 (exidle,O_AO_QUEUE); /* restart the processing */ 


The above code fragment assumes that the active object exists for the lifetime of the application; its 
creation and destruction would be handled elsewhere. 


If the active object is to have a transient existence, it would normally be created (with the appropriate 
error handling) immediately prior to its use. In this case it would be appropriate for the object to send 
itself a DESTROY message in its ao_run method on completion of the processing. 


12-4 


CHAPTER 13 


TIMER ACTIVE OBJECT CLASSES 


This chapter describes the TIMER class and two TIMER subclasses, ANIMATOR and BUZSND. 


The Trmer class, although not formally an abstract class, must be subclassed to provide a specific ao_run 
method to process the timer expiry. 


Class diagram 


fe ee 
¢ active / 


timer / 


a? 
~\. 

[or Te 
¢ animator/ ~ buzsnd / 


- mye ) 


Ne ad 


—~— 


C 
fy 
f- —_—~ 
Precursors 


The reader is assumed to understand: 
e the active class. 
e the PLIB/EPOC timer driver services. 


e = for BuzsND, the EPOC sound driver services 


13-1 


OLIB REFERENCE 


TIMER 


ACTIVE 


gq 
priority 
isactive 
pcb 

stat 


destroy ao_init 
aorinit ao_queue 
ao_cancel tm_qabsolute 


ao_abrun 


The T1rmer class supplies methods to queue both relative and absolute timers. See the Time, Timers and 
Dates chapter of the PLIB Reference manual for a description of absolute and relative timers and their 
differences. 


Class definition 
Defined in sub-category file timer.cl (generated header file timer.g). 


CLASS timer active 
The timer active object 


{ 


REPLACE ao_init Opens a channel to an asynchronous timer 
REPLACE ao_queue Queues a relative timer 
ADD tm_qgabsolute Queues an absolute timer 
} 
Property 
None. 


TIMER methods 


AO_INIT Initialise 


VOID ao_init (VOID) ; 


Open a channel to a timer using the device name "T1m:" by supersending the ao_tnrT message. This uses 
the PLIB p_open function. 


The open timer channel handle will be stored in active.pcb if the timer was successfully opened. 


Calls p_1eave on error. 


J AO_QUEUE Queue (relative) 


VOID ao_queue(UINT lsw, UINT msw); 
VOID ao_queue(ULONG time) ; (conceptual) 


Queue a request on the timer for a relative timeout (using active.stat as the completion status word) 
where time is the required time interval to the timer completion in tenths of a second. The uLonc time is 
actually passed in the message as two UINT parameters, 1sw (least significant word) and msw (most 
significant word). 


Sets active.isactive tO TRUE. 


Only one timer request (either relative or absolute) may be outstanding at any one time since active.stat 
is used for either timer request. 


The timer will receive an ao_RUN message on expiry of the timeout. 


13-2 


13. TIMER ACTIVE OBJECT CLASSES 


J TM_QABSOLUTE Queue (absolute) 


VOID tm_qabsolute(UINT lsw, UINT msw); 
VOID tm_qabsolute(ULONG time); (conceptual) 


Queue a request on the timer for an absolute timeout (using active.stat as the completion status word) 
where time is the absolute system time at which the timer is to complete. The uLonc time is actually 
passed in the message as two uINT parameters, 1sw (least significant word) and msw (most significant 
word). 


Sets active.isactive tO TRUE. 


Only one timer request (either relative or absolute) may be outstanding at any one time since active.stat 
is used for either timer request. 


The timer will receive an ao_RUN message on expiry of the absolute timeout. 


ANIMATOR 


gq own 


priority message 


isactive interval 


The anrmator class supplies the functionality to send a message to an object at regular intervals, the 
message, object and time interval being specified at initialisation. 


Since the intention is that antmator will be used to drive an animation sequence, it runs at a priority 
which is much higher than that normally used by timers but which, at the same time, is less than 
PRIORITY_ACTIVE_WSERV So that window server events - particularly redraw events resulting from the 
animation - are not blocked. The actual priority is set to PRIORITY_ACTIVE_WSERV - 1. 


Class definition 
Defined in sub-category file timer.cl (generated header file timer.g). 


CLASS animator timer 

Sends regular messages eg to drive animation 
{ 
REPLACE ao_init 
REPLACE ao_run 


TYPES 
{ 
typedef struct Must be in property order 
{ 
PR_ROOT *own; send messages to this object 
INT message; message number to send 
INT interval; delay between subsequent messages in tenths of a second 
INT first; delay before first message back in tenths of a second 
} IN_ANIMATOR; 
} 
PROPERTY 
{ 
PR_ROOT *own; send messages to this object 
INT message; the number of the message to send 
INT interval; interval between messages 


} 


13 -3 


OLIB REFERENCE 


Property 
animator.own the handle of an object to which messages will be sent (this will normally 
be the object which owns the instance of anrmaTorR) 
animator.message the number of the message to be sent to animator.own 
animator.interval the time interval, in tenths of a second, between the sending of two 


successive messages 


ANIMATOR methods 


AO_INIT Initialise 


VOID ao_init (IN_ANIMATOR *pin) ; 
Initialise the animator object by: 
¢ supersending an AO_INIT message, which opens a timer channel 


e setting active.priority to PRIORITY_ACTIVE_WSERV-1 and sending the application manager an 
AM_ADD_TASK message to add the animator object to the application manager's active object task 
queue. 


e setting up animator.own, animator.message and animator.interval from the data pointed to by pin. 


e sending itself an AO_QUEUE message with the interval timeout value specified by pin->first. In 
effect, this defines the time interval before the animator object receives the first Ao_RUN message. 


AO_RUN Run 


INT ao_run(VOID) 

Handle the completion of the timer request by: 

e sending the message animator.message to the object animator.own 

e sending itself an AO_QUEUE message with the timeout value specified by animator.interval 


e returning RUN_ACTIVE_USED 


BUZSND 


ACTIVE TIMER BUZSND 


q snd 
priority sndrep 
isactive sndnum 
pcb snddelay 
stat sndvolume 
h_done 


m_done 


tm_qabsolute ao_init 


aorinit ao_cancel 


aerqueu ao_queue 


ao_run 


The suzsno class provides the means for an application to generate alarm sound sequences. 


Each alarm sequence consists of one of two possible sounds repeated eight times with a two second 
interval between each sound. The volume of the sound is increased with each repetition. 


13-4 


13. TIMER ACTIVE OBJECT CLASSES 


The sound itself can be either a 'rings' sequence or a 'chimes' sequence and is selected when an ao_INIT 
message is received. 


The sounds are generated by means of the sound driver as described in the Sound chapter of the I/O 
Devices Reference manual. Since only one user may have access to the sound system at any one time, 
BUZSND Serialises multiple access requests from different applications. To avoid monopolising the sound 
driver, the channel is opened and closed for each sound in the sequence. 


This active object is interesting, in that it may have an outstanding request on either the sound or the 
timer channel, but not both at the same time; the two channels alternately use active.isactive and 
active.stat. The descriptions of the ao_cance1 and the ao_run methods include sample code to clarify 
the explanation of the techniques involved. 


Class definition 
Defined in sub-category file timer.cl (generated header file timer.g). 


CLASS buzsnd timer 
Buzzer sound generator 


{ 


REPLACE ao_init Init timer and add to appman task list 
REPLACE ao_cancel Cancel the timer or sound 
REPLACE ao_queue Start a sound 
REPLACE ao_run Handle next step of sound sequence 
PROPERTY 
{ 
UBYTE *snd; Open sound channel handle 
UWORD sndrep; Number of repeats to do 
UWORD sndnum; Which sound number to use 
UWORD snddelay; Delay between repeats 
UWORD sndvolume; For SND: growing volume 
PR_ROOT *h_done; Handle to receive completion message 
UWORD m_done; Method number for above 
} 
} 
Property 
buzsnd.snd the channel handle of the sound driver, while the sound driver is being 
used. 
buzsnd.sndrep the remaining number of repetitions in the current sound sequence 
buzsnd.sndnum which sound to use (0 for a 'rings' sequence or | for a 'chimes' sequence) 
buzsnd.snddelay the time, in tenths of a second, of the delay between successive sounds 
buzsnd.sndvolume the volume of the current sound in the sequence 
buzsnd.h_done NULL, or the handle of the object to which a message is sent on completion 


of the sound sequence 


buzsnd.m_done the message number to be sent on completion of the sound sequence 


BUZSND methods 
AO_INIT Initialise 


VOID ao_init (UINT sndnum) ; 


Open a timer device channel by supersending an ao_InrIT message to the T1mer superclass, store sndnum 
(either a O for a 'rings' sequence or a | for a 'chimes' sequence ) in buzsnd.sndnum, Set appman.priority 
to PRIORITY_ACTIVE_REPEATER and send the application manager an aM_ADD_TASK message. 


Calls p_1eave on error, typically with the error z_GEN_NOMEMoRY. 


13-5 


OLIB REFERENCE 


J AO CANCEL Cancel 


VOID ao_cancel (VOID) 
Cancel either the timer or the sound driver, whichever is currently running. 


If the sound channel is open (buzsnd.snd is non-zero), any outstanding request is cancelled using the 
PLIB I/O p_rcancet service. The sound channel is closed and buzsnd.snd is set to NULL so that further 
closes are harmless. 


In all cases the ao_cance1 method then supersends an ao_caNcEL message to cancel any outstanding timer 
request. As with all ao_cance1 methods, this is harmless if there is no outstanding request. 


Finally, buzsnd.sndrep and buzsnd. snddelay are Set to their starting values of 8 and 20 (i.e. 
20 by 1/10th second) respectively, and buzsnd. sndvolume is set to one of two starting values depending on 
whether the user has set the machine to generate loud or quiet sounds. 


METHOD VOID buzsnd_ao_cancel (PR_BUZSND *self) 
{ 
if (self->buzsnd.snd) /* destroy may call cancel if init fails */ 
{ 
p_iow2 (self->buzsnd.snd,P_FCANCEL); /* all harmless if not running */ 
p_waitstat (&self->active.stat); /* see note ++ */ 
self—>active.isactive=FALSE; /* see note ++ */ 
p_close(self->buzsnd.sndqd); 
self-—>buzsnd.snd=NULL; 
} 
p_supersend2 (self,O_AO_ CANCEL); /* timer cancel is harmless if not running */ 
self—>buzsnd.sndrep=8; 
self->buzsnd.snddelay=20; /* in tenths of a second */ 
self—>buzsnd.sndvolume=(p_getsnd() &E_SOUND_LOUD) ? 
(E_SOUND_MIN_VOLUME-1) *2+1: (E_SOUND_MIN_VOLUME) *2+1; 
} 


While the calculation for buzsnd.sndvolume in the last line of the code is obscure, it does represent the 
most efficient way (in conjunction with the ao_run method) of calculating a gradually increasing volume. 


Note 


For the byte-conscious programmer, these two lines (marked ++) are not strictly necessary. These actions 
will be performed within the p_supersend of an ao_canceL which follows a few lines further down. This 
relies on the fact that the timer and sound channels share the same status word and never have 
simultaneous outstanding requests. 


J AO_QUEUE Queue 


VOID ao_queue(PR_ROOT *handle, UINT method); 
Start the generation of a sound sequence. 


Any currently outstanding sound being generated is cancelled by sending itself an ao_caNcEL message, 
which also resets the sound control parameters buzsnd. sndvolume, buzsnd.sndrep and buzsnd. snddelay 
to their starting values. The handie and method values are stored in buzsnd.h_done and buzsnd.m_done 
respectively. 


The sound generation sequence is started off by setting active.isactive to TRUE and calling p_iosignal. 


The ao_run method will be called by the active object scheduling code in the application manager when 
no other events of higher priority are outstanding. 


AO_ RUN Run 


INT ao_run (VOID) 
Make alternate requests for a sound or a timeout until the sound sequence is complete. 
If the last to run was the sound driver: 

e the sound driver is closed and buzsnd. snd is set to NULL 


e if the sound sequence is not complete, the timer is queued by supersending an ao_QUEUE message 
with a timeout as defined by buzsnd.snddelay (2 seconds). 


13 - 6 


13. TIMER ACTIVE OBJECT CLASSES 


if the sound sequence is complete and buzsnd.h_done is non-zero, a buzsnd.m_done message is 
sent to buzsnd.h_done. 


If the last to run was the timer: 


an attempt is made to open the sound driver 
if the sound driver is currently busy, a five second timeout is queued 


if the sound driver has been disabled then the sound sequence is deemed to have completed and 
the completion message is sent, as described above 


if the sound driver cannot be opened for any other reason (e.g. insufficient memory being 
available) then p_ieave is called. 


if the sound driver is opened successfully, the volume is adjusted so that it gradually becomes 
louder and an asynchronous request is made to generate an alarm sound (this branch requires 
active.isactive to be explicitly set to TRUE) 


In all cases the method returns RUN_ACTIVE_USED. 


METHOD buzsnd_ao_run(PR_BUZSND *self) 


{ 

INT ret; 
UWORD delay; 
UBYTE bb[10]; 
E_SOUND c; 


if (!self->buzsnd.snd) 
{ /* last to run was the timer */ 


bb[0]='S';bb[1]='N';bb[2]='D';bb[3]=':';bb[4]=0; 
ret=p_open (&self—>buzsnd.snd, &bb[0]); 
if ((ret==E_FILE_LOCKED) || (ret==E_GEN_INUSE) ) 


{ /* busy - try again later */ 
delay=50; /* 5 seconds */ 
p_supersend4 (self,O_AO_QUEUE,delay,0); /* last 2 parameters are a LONG */ 
} 
else 
{ 
if (ret==E_GEN_FAIL) /* sound driver disabled */ 
goto sendOwnerDone; /* immediate completion (silent alarm) */ 
f_leave (ret); 
p_iow3 (self—>buzsnd.snd, P_FSENSE, &c) ; 
c.volume=(self-—>buzsnd.sndvolume-—) >>1; 
p_iow3 (self—>buzsnd.snd,P_FSET, &c) ; 
p_ioc4 (self—>buzsnd.snd, E_FALARM, &self—>active.stat, &self-—>buzsnd.sndnum) ; 
self—>active.isactive=TRUE; 


else 
{ /* last to run was the sound */ 
p_close(self->buzsnd.snd); 
self—>buzsnd.snd=0; 
if (--self->buzsnd.sndrep) 
{ 
p_supersend4 (self,O_AO_QUEUE, self—>buzsnd.snddelay, 0); 
/* last 2 pars are a LONG */ 
} 
else 
{ 
if (self->buzsnd.h_done) + 
p_send2 (self-—>buzsnd.h_done, self—>buzsnd.m_done) ; 


} 


return (RUN_ACTIVE_USED) ; 
} 


13-7 


CHAPTER 14 


FILE ACTIVE OBJECTS 


This chapter describes the ractive class (subclassed by all active objects which perform asynchronous 
operations on files) and its FScAN, FNODE, Fcasy and Fcsync subclasses. 


Precursors 


The reader is assumed to understand: 
e the acTIvE class 


e the file server and file system services as described in the Files chapter of the PLIB Reference 
manual 


Class diagram 
i 
¢ active / 
Ss ) 


7 
fe es 


¢ factive / 


pe aw fo ae ee ae 


la fscan / ¢ fnode / la feasy / ‘4 fesyne / 
2. =i) > a fee FS _) 


Qo Ke er ee ke ee 


FACTIVE 


ACTIVE FACTIVE 


q owner 


priority 


isactive 
pcb 
stat 


destroy fa_close 
ao_init 
ao_cancel 
ao_abrun 
ao_queue 


ao_run 


14-1 


OLIB REFERENCE 


The ractrve class provides the basic functionality of all active objects that perform operations on files. 


Although not formally an abstract class, ractrve must be subclassed to be useful. The subclass will, in 
general, need to supply at least an ao_queue and an ao_run method. 


Although the file server does not support a cancel service (see the Files chapter of the PLIB Reference 
manual) ractive supplies an ao_cance1 method which simulates the cancelling of an outstanding 
asynchronous request. This allows the coding of file-related active objects to follow the style of coding for 
other active objects which, for example, routinely send an ao_caNcEL message prior to destruction of the 
instance. 


Class definition 
Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS factive active 


File active object superclass 


{ 


REPLACE ao_init Set priority and am_add_task 
REPLACE ao_cancel Simulate cancel and close file 
REPLACE ao_abrun Cancel and supersend 
ADD fa_close Close and set pcb to NULL 
PROPERTY 
{ 
UBYTE *owner; Owning object 
} 
} 
Property 
factive.owner the handle of the owning object, for use by subclasses, for example, to 


report the completion of file activity - not used by racTIvE 


FACTIVE methods 
& AO_INIT Initialise 


VOID ao_init (UBYTE *owner) ; 
Initialise the file active object by: 
e — setting factive.owner to owner, the handle of the owning object 
e setting active.priority to PRIORITY_ACTIVE_FILES 


e sending the application manager an AM_ADD_TASK message to add the file active object to the 
application manager's active object task queue 


& AO CANCEL Cancel 


VOID ao_cancel (VOID); 


Cancel any outstanding file server event and close any open file. This is harmless if there is no 
outstanding event. 


Note that the cancellation is simulated since the file server does not support a cancel service (see 
Asynchronous file operations in the Files chapter of the PLIB Reference manual). The end effect is, 
however, indistinguishable from a true cancel in that, if a file server event is outstanding, active.stat is 
set to E_FILE_CANCEL and active.isactive iS set tO FALSE. 


In addition, this method sends an ra_cLosE message to ensure that any open file is closed. 


14-2 


14 FILE ACTIVE OBJECTS 


AO_ABRUN Handle error 


VOID ao_abrun (VOID) ; 


Send itself an ao_caNcEL message to cancel any outstanding file activity and close any open file and then 
supersend an Ao_ABRUN message. 


This may leave with any error that could arise in the superclass ac_abrun method. 


& FA_CLOSE Close any open file 


VOID fa_close(VOID); 
Close (with p_close) any open file whose handle is in active.pcb, and set active.pcb tO NULL. 


This method does not call p_ieave. It is a requirement that any subclass must not call p_leave. 


FSCAN 


ACTIVE FACTIVE 
q 


owner flags 
priorityt index 
isactive pname 
pcb match 
stat delim 
finfo 
cork 
pcbarr 


name 


destroy #a—cetese fs_matchname 


ao_init fs_fscan 
ao_cancel ao_queue 
ao_abrun ao_run 


fa_close 


fs_fscan_end 
fs_dirname 
fs_filename 
fs_end_dirlist 


FSCAN Is an abstract subclass of ractive which provides the basic mechanisms for scanning a filing 
system by reading the content of one or more directory files. It is designed to be independent of any 
particular filing system and can be used, for example, with either Macintosh or DOS-compatible filing 
systems. 


Subclasses of rscan may be used to scan the filing system to select files which match any of a variety of 
criteria. The subclass must supply the action(s) required when a matching directory or file is found. 


It may be noted that on completion of the scan, the whole of each relevant directory file will always have 
been read; files are eliminated by the matching process within the rscan code. This allows, for example, 
subclasses of rscan to extract multiple file specifications in one scan of the directory file or to build file 
name extension lists. 


14-3 


OLIB REFERENCE 


Class definition 


Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS fscan 
Scans the directory structure for files/dirs and creates variable str arrays 


{ 


factive 


REPLACE ao_queue 
REPLACE ao_run 
REPLACE fa_close 
ADD fs_matchname 
ADD fs_fscan 
DEFER fs_fscan_end No more files/dirs 
DEFER fs_dirname 
DEFER fs_filename 
DEFER fs_end_dirlist End of that subdir 


CONSTANTS 
{ 


Queue a directory read 

Process read completion 

Close all open directory files 
Match a found name 

Start a directory scan 


Next directory name from scan 
Next file name from scan 


! Which types of files caller wants 
FS_WRITABLE 


FS_HI 


DDEN 


FS_SYSTEM 
FS_DIRECTORIES 


FS_MO 


DIFIED 


FS_ALL_FILES 


FS_FI 


LE_TYPE 


P_FAWRITE opposite of DOS Read-only attribute 
P_FAHIDDEN as DOS Hidden attribute 

P_FASYSTEM as DOS System attribute 

P_FADIR 

P_FAMOD as DOS Archive attribute 

P_FAREAD 

(FS_HIDDEN|FS_SYSTEM) 


FS_INCLUDE_SUBDIRECTORIES 0x1000 Want files from subdirectories 
FS_INCLUDE 


FS_EN 


D_DIRLIST 


FS_PARSE_NAME 
FS_MAX_DIRLEVE 


} 


PROPERTY 
{ 
UWORD 
UWORD 
UBYTE 
UBYTE 
UBYTE 


} 
} 


Property 


fscan. 


fscan. 


fscan. 


fscan. 


fscan. 


fscan. 


14-4 


flags 


index 


pname 


match 


delim 


finfo 


flags; 
index; 
*pname; 
*match; 
delim[2] 


P_INFO finfo; 
P_FPARSE crk; 
UBYTE *pcbarr[FS_MAX_DIRLEVELS] ; 
UBYTE name[P_FNAMESIZE]; 


0x2000 Called dirname because of include 

0x4000 Called end dir list 

0x8000 Set if generated name to be parsed 
LS 32 Max number of sub dir levels 


Controlling flags 
Subdir array index 
Pointer into name[] for read 
Pointer to file name match 
, 
File Info 
Parsed file info 


controlling flags, some of which should be set up by the owner before 
sending an Fs_FSCAN message 


the index of the first free entry in the fscan.pcbarr array. It should not be 
accessed by any subclass. 


a pointer to the file name and extension within the full file specification in 
the fscan.name buffer. Owners and subclasses should treat this as a read- 
only field. 


a pointer to a string used to match file names during a scan. It may be set 
up by an owner before sending an rs_Fscan message. 


temporary storage for the directory delimiter character (assumed to be a 
single character). It should not be accessed by any subclass. 


the PLIB p_inro data for the current file, that is, the file whose name has 
last been read from a directory file. This information may be read, but 
should not be modified, by an owner. 


14 FILE ACTIVE OBJECTS 


fscan.crk provided the rs_parsE_NawE flag is set in fscan. flags, this contains the 
PLIB p_rparse data for the current file, whose full file specification is in 
the fscan.name buffer. This information may be read by an owner. 


fscan.pcbarr an array of up to Fs_MAX_DIRLEVELS handles of open directory files. This 
should not be accessed by a subclass. 


fscan.name the full file specification of the current file. An owner may read this name 
directly or may read only the file name via fscan.pname. 


FSCAN methods 
AO_QUEUE Directory read 


VOID ao_queue (VOID) ; 
Queue a read on the current directory file, setting active.isactive tO TRUE. 
The action may be modified by the ao_run method resulting from a previous read: 


e If the previous read produced the name of a directory file and the scan is to extend into nested 
subdirectories (fscan. flags includes rs_INCLUDE_SUBDIRECTORIES) the current value of 
active.pcb Is stored in the fscan.pcbarr array and the new subdirectory is opened before the 
read request is made. A maximum of 32 levels of subdirectory may be open at any one time. 


e If the previous read detected that there were no more files in the current directory and directories 
have been nested, then the most recently nested subdirectory handle is restored into active.pcb 
from the fscan.pcbarr array before the read request is made. 


Any error causes p_leave to be called. 


AO_RUN Process read completion 
INT ao_run(VOID); 
Process the completion of the read of a file name from a directory file and return RUN_ACTIVE_USED. 


If the read completed with an £_rF1LE_zoF error, indicating that there are no further entries in the current 
directory file:- 


e the file is closed and active.pcb is Set to NULL. 


e The delimiter character is picked up (the last character before the filename) and placed in 


fscan.delim. 
If directories are nested:- 
@ an FS_END_DIRLIST message is sent to indicate the end of a directory, but not the end of the scan. 
e the run method completes and returns RUN_ACTIVE_USED 
If directories are not nested:- 
@ an FS_FSCAN_END message is sent to indicate the end of the scan. 
e the run method completes and returns RUN_ACTIVE_USED 
If the read completed successfully:- 


e if the file name is a volume name, the name is discarded and a new name is requested by calling 
the FScAN ao_queue method directly. 


e if none of the flags rs_WRITABLE, FS_HIDDEN, FS_SYSTEM, FS_MODIFIED, FS_ALL_FILES Is Set, the 
name is discarded and a new name is requested by calling the rscan ao_queue method directly. 


e if the file is a (DOS) . or .. directory file, the name is discarded and a new name is requested by 
calling the rscan ao_queue method directly. 


14-5 


OLIB REFERENCE 


e if the file is a directory file and either of the rs_DIRECTORIES OF FS_INCLUDE_SUBDIRECTORIES 
flags is set (meaning that there is interest in the directory file name itself or in subdirecrtories) 
then an Fs_DIRNAME message Is sent. If neither flag rs_DIRECTORIES or 
FS_INCLUDE_SUBDIRECTORIES Is set, the name is discarded and a new name is requested by 
calling the rscaNn ao_queue method directly 


if the file is not a directory file:- 


e flag is set, then the file name in fscan.name is parsed (using p_fparse) with the parsed file name 
information written to fscan.crk. 


e an FS_MATCHNAME message is sent. If this returns FaLsz, indicating that the file name does not 
match the specified attributes and (wildcard) name, the name is discarded and a new name is 
requested by calling the rscan ao_queue method directly. If the rs_maTcHNamE message returns 
TRUE then the read of a valid, matching, file name is indicated by sending an rs_FILENAME 
message. 


e the run method completes and returns RUN_ACTIVE_USED. 


All errors, other than the z_F1LE_zor error discussed above, result in p_leave being called. 


& FA_CLOSE Close directory files 


VOID fa_close (VOID) ; 


Supersend an ra_cLosgE message and close all open directory files. 


& FS_MATCHNAME Match a found name 


INT fs_matchname (VOID) ; 


Check that the file matches the specified combination of rs_MoDIFIED, FS_HIDDEN and Fs_systTen flags. If 
these tests succeed the file name (pointed to by fscan.pname) 1s tested for a match with the (wildcard) 
name pointed to by fscan.match. 


Note that the name match is case-sensitive. Since rscan is designed to work independently of any 
particular filing system, matching uses a true wildcard string match (as opposed to a DOS-specific file 
system wildcard match) to select files. Thus the wildcard string "*" will select all files (including those 
with an extension, unlike DOS). This also means that more than one part of a file name can be wildcarded 
with the '*' character, to find, for example, files matching "*fred.*". 


Returns true if there is a match, otherwise raLsE. 
This method is called from within the ao_run method. 


A subclass may replace this method to provide an alternative name matching algorithm. 


FS FSCAN Start a directory scan 


VOID fs_fscan(UBYTE *path); 
Start the scan of the file system for directories and files. 


The file specification pointed to by path is parsed to extract the directory in which the scan is to start. 
Provided this initial path name does not need to be preserved, path may point to a file specification in 
fscan.name (this field is overwritten during the scan). 


If the specified directory is opened successfully, an ao_quEUE message is sent to start the scan. 
Any error causes p_leave to be called. 


It is assumed that fscan.match and fscan. flags have previously been set up either by a subclass or by 
the owner as is done, for example, by many of the methods (such as fman_rename) of the rman class, 
described in the File Management Classes chapter. 


The fscan.match field should be set to point to a suitable wildcard string. 


14-6 


14 FILE ACTIVE OBJECTS 


The fscan. flags field should contain a bitwise combination of one or more of the following values: 


FS_ALL_FILES include all non-directory files that are neither hidden nor system files 
FS_WRITABLE aS FS_ALL_FILES, but excludes write-protected files (see below) 
FS_HIDDEN include hidden files 

FS_SYSTEM include system files 

FS_DIRECTORIES include directory files 

FS_MODIFIED exclude unmodified files (include only files that have p_ramop set) 
FS_INCLUDE_SUBDIRECTORIES extend the scan to subdirectories 

FS_PARSE_NAME parse file names before reporting them 


The supplied £s_matchname method does not test the rs_wR1ITABLE flag which therefore has the same 
effect as the rs_att_Fiues flag. A subclass fs_matchname method may implement this flag as follows: 


if ((self->fscan.flags&FS_WRITABLE) && !(self->fscan.finfo.status&P_FAWRITE) ) 
return (FALSE) ; 
return (p_supersend2 (self,O_FS_MATCHNAME) ) ; 


Deferred FSCAN methods 


FS FSCAN_END Scan completion 


VOID fs_fscan_end(VOID); 


A deferred method indicating the end of the scan and that there are no more files or subdirectories to scan 
into or report back. 


This message is sent from within the ao_run method. By the time it is sent, all levels of directory files will 
have been closed. 


FS DIRNAME Next directory name 


VOID fs_dirname (VOID) ; 
A deferred method indicating that a directory file matching the initial specification has been found. 


This message is sent from within the ao_run method, provided that fscan. flags includes either 
FS_DIRNAME Of FS_INCLUDE_SUBDIRECTORIES. 


On receipt of this message fscan.finfo contains the file information for the directory file, fscan.name 
contains its full file specification and the fscan.pname points to the directory file name within the full file 
specification. These fields should be regarded as read only. 


In order to obtain further files or directories, this method must restart the scan by sending an ao_QUEUE 
message. 


FS_FILENAME Next file name 


VOID fs_filename (VOID) ; 


A deferred method indicating that a file name matching the initial specification has been found. This 
message is sent from within the ao_run method. 


On receipt of this message fscan.finfo contains the file information for the file, fscan.name contains its 
full file specification and the fscan.pname points to the file name within the full file specification. If 
fscan.flags includes rs_PARSE_NaME, then fscan.crk contains the parsed file name information. These 
fields should be regarded as read only. 


In order to obtain further files or directories, this method must restart the scan by sending an ao_QUEUE 
message. 


14-7 


OLIB REFERENCE 


FS _END_DIRLIST End of subdirectory 


VOID fs_end_dirlist (VOID); 


A deferred method indicating that the end of a subdirectory has been reached. This message is sent from 
within the ao_run method provided that fscan. flags includes rs_INCLUDE_SUBDIRECTORIES. It is only 
reported at the end of a nested subdirectory and not when the end of the directory in which the scan 
started is reached. The directory file will be closed before this message is sent. 


On receipt of this message fscan.name contains the full file specification of the directory file and the 
fscan.pname points to the file name within the full file specification. The information in fscan.finfo and 
fscan.crk is not valid. 


In order to obtain further files or directories the scan must be restarted by sending an aco_quEuUE message at 
some point. 


FNODE 


ACTIVE FACTIVE 
q 


owner flags 
priority pname 
isactive oldname 
pcb pcb 
stat 


destroy #a—cteose fn_list 


ao_init ao_queue 
ao_cancel ao_run 


ao_abrun fa_close 


fn_end_list 


fn_nodename 


In EPOC there are multiple filing systems, three of which are ROM::, LOC:: and REM::. The rnopE 
abstract class provides the basic mechanisms to generate filing system node and device lists. 


The rnope methods read an item in the filing system (node) list and, if that node supports multiple devices 
(drives) read the device list to generate a node: :device.:\ name. Filing systems (such as ROM-::) that do not 
support multiple devices are ignored. 


It is possible to restrict the list to the LOC:: filing system. 


Since filing systems are dynamic under EPOC, the names generated may vary between invocations. 


14-8 


14 FILE ACTIVE OBJECTS 


Class definition 
Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS fnode factive 
Node/Device name list generator 


{ 


REPLACE ao_queue Read from appropriate channel 
REPLACE ao_run Process read completion 
REPLACE fa_close Closes both open channels 
ADD fn_list Start to generate a list 
DEFER fn_end_list Handle list generate completion 
DEFER fn_nodename Process an item in the list 
CONSTANTS 
{ 
FNODE_NODE_ARRAY 0x01 Reading node list 
FNODE_DEVICE_ARRAY 0x02 Reading device list 
FNODE_LOCAL_ONLY 0x04 Read local node list only 
} 
PROPERTY 
{ 
UWORD flags; Controlling flags 
UBYTE *pname; Where to read into 
UBYTE *oldname; Node read ptr 
UBYTE *pcb; Node pcb while reading device list 
} 
} 
Property 
fnode.flags internal controlling flags 
fnode.pname the offset into the data buffer of where to write the node or device name. It 


should not be accessed by an owning object. 


fnode.oldname the offset into the data buffer of where to read the next node name. It 
should not be accessed by an owning object. 


fnode.pcb while reading a device list, the handle of the opened node list file is saved 
here. It should not be accessed by an owning object. 


FNODE methods 
& AO_QUEUE Read from appropriate channel 


VOID ao_queue (VOID) ; 


Queue a read on either the node list or device list, depending on which is appropriate at the time and set 


active.isactive tO TRUE. 


Note that node information as would be written to a p_NInFo structure is not requested in the read. 


AO_RUN Process read completion 


INT ao_run(VOID); 


Process the completion of a read that was initiated by the ao_queue method and return RUN_ACTIVE_USED. 
The read may have been from either the node list or a device list. The two cases are discussed under their 
respective headings. 


Node List Read 


The completion status is tested for an E_FILE_£oF error, indicating that no further nodes exist; if this is 
the case, the scan is terminated by closing the node list and sending an rN_END_LIsT message. Otherwise, 
the node is checked for validity:- 


e the node must support multiple devices 


e if the FNopE_LocaL_onty flag is present, only the LOC:: node is valid. 


14-9 


OLIB REFERENCE 


For a valid node, the device list for that node is opened and an ao_QuzuUE message sent to read an item 
from the device list, otherwise an ao_QuEUE message is sent to read a further item from the node list. 


Device List Read 


The completion status is tested for an =_FILE_EoF error, indicating that no further devices exist on the 
current node. If the completion status is E_FILE_EOF:- 


e the device list is closed 
@ an AO_QUEUE message is sent to read the next item from the node list. 
If the read completed successfully, an rN_NODENAME message is sent. 


The owner is responsible for re-queuing a read on the node/device list by sending an ao_quEUE message at 
some future point after sending the rn_NODENAME message. 


For all errors other than the z_riLe_zor errors discussed above, p_leave is called. 


& FA_CLOSE Close both open channels 


VOID fa_close (VOID) ; 


Close any open node and device lists setting both the open handles to nun. The node list is closed by 
supersending an ra_cLosE message; the device list is closed by calling p_close. 


FN_LIST Start list generation 


VOID fn_list (UBYTE *pname, UINT flags); 


Start the scan to generate node: :device:\ names by opening the node list and sending an ao_QuEUE 
message. 


The user-supplied buffer at pname is assumed to be at least p_rNames1zeE bytes in length. It is used as the 
output buffer for each generated name and hence, must be preserved until an FN_END_LIST message is 
received. The user may access this buffer only when no read is outstanding, for example, during the 
processing of the deferred rN_NODENAME message. 


The value of f1ags may be either rNopE_LocAL_oNLy to read only the LOC:: filing system, or nuu1 to read 
all filing system device lists. 


Deferred FNODE methods 
FN_END LIST Handle completed list 


VOID fn_end_list (VOID) ; 


A deferred method indicating that the scan is complete and that all node: :device:\ names have been 
generated. 


On receipt of this message the node and device lists will have been closed. The user-supplied buffer (see 
the fn_1ist method) may now be discarded. 


FN _NODENAME Process a list item 


VOID fn_nodename (VOID) ; 


A deferred method indicating that a node: :device:\ name has been generated. The name may be read from 
the user-supplied buffer (see the fn_1ist method). 


The user is responsible for restarting the scan for the next name by sending an ao_QuEUE message. 


14-10 


14 FILE ACTIVE OBJECTS 


FCASY 


ACTIVE FACTIVE 
q 


owner recvname 
priority flags 
isactive 

pcb 

stat 


destroy ao_cancel 


ao_init ao_run 

aereancet ao_queue 

ao_abrun fa_close 
fc_write 


fc_open 


fc_request_comp 


The rcasy abstract class subclasses ractIve to provide a set of methods to perform a segmented read or 

write of a single file. In other words, it allows a file to be read or written to in a finite number of discrete 
portions. This permits a large file to be processed (which would otherwise be impossible due to memory 

constraints) 


Fcasy does not support a combination of reading and writing to the same file. 


Typical uses are in copying a file or in XMODEM file transfer, where the source and target files are each 
represented by a separate instance of a subclass of rcasy. 


Class definition 
Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS fcasy factive 
File copy/save/load asynchronous routines 


{ 


REPLACE ao_cancel Abandon and clean up correctly 

REPLACE ao_run Maybe cleanup and send itself fc_request_comp 
REPLACE ao_queue Async file read 

REPLACE fa_close Close file, set recname to NULL 

ADD fc_write Async file write 

ADD fc_open Open/create file for load/save 

DEFER fc_request_comp That async request has completed 

CONSTANTS 


{ 

! Display info flags 
FCOPY_DISP_SFTYPE 0x01 
FCOPY_DISP_SFSIZE 0x02 
FCOPY_DISP_SFDATE 0x04 
FCOPY_DISP_SFNAME 0x08 
FCOPY_DISP_RFTYPE 0x10 
FCOPY_DISP_RFSIZE 0x20 
FCOPY_DISP_RFDATE 0x40 
FCOPY_DISP_RFNAME 0x80 
FCOPY_DISP_BLKSIZ 0x100 
FCOPY_DISP_BLKNO 0x200 
FCOPY_DISP_PROTOCOL 0x400 

! Controlling Flags 
FCASY_READ_QUEUED 0x01 
FCASY_WRITE_QUEUED 0x02 
} 


14-11 


OLIB REFERENCE 


TYPES 


{ 
typedef struct 


{ 


UWORD flags; FCOPY_DISP_... flags indicate which fields are 
valid 
UWORD protocol; Which protocol being used 
UWORD blksiz; Size of each block 
UWORD blkno; Current block number 
UWORD sftype; Source file type 
UWORD rftype; Receive file type 
ULONG sfsize; Source file size 
ULONG rfsize; Receive file size 
ULONG sfdate; Source file last modification date 
ULONG rfdate; Receive file last modification date 
UBYTE *sfname; Source file name (source for reads) 
UBYTE *rfname; Receive file name (destination for writes) 
} FCOPY_DISP; 
} 
PROPERTY 
{ 
UBYTE *recvname; Receive file name 
UWORD flags; Controlling flags 
} 
} 
Property 
fcasy.recvname a pointer to the name of the file being written to (nut if the file is being 
read) 
fcasy.flags internal controlling flags; while a request is outstanding, contains a value 


indicating the nature of the request (either rcasy_READ_QUEUED or 
FCASY_WRITE_QUEUED) 


FCASY methods 
& AO_CANCEL Cancel request 


VOID ao_cancel (VOID); 
Cancel any outstanding read or write by supersending an ao_cANCEL message. 


If the instance represents a file that is opened for writing, the file is then explicitly deleted. 


& AO_QUEUE Read request 


VOID ao_queue(UBYTE *buf, UWORD *plen); 
Queue a read of *pien bytes into buf from the file whose channel handle is in active.pcb. 


Sets active.isactive to TRUE and sets the rcAsy_READ_QUEUED flag in fcasy. flags to indicate a read 
request. 


Since the read is asynchronous, the memory pointed to by buf and plen must be preserved until the 
request completes. 


& FC_WRITE Write request 


VOID fc_write(UBYTE *buf, UWORD *plen); 
Queue a write of *pien bytes from bug to the file whose channel handle is in active.pcb. 


Sets active.isactive to TRUE and sets the FcAsy_WRITE_QUEUED flag in fcasy. flags to indicate a write 
request. 


Since the write is asynchronous, the memory pointed to by buf and pien must be preserved until the 
request completes. 


14-12 


14 FILE ACTIVE OBJECTS 


AO_RUN Process read or write completion 


INT ao_run(VOID); 
Process the completion of either a read or a write request. 


Note that the object is expected to handle the completion of either a read request (Aao_QUEUE) or a write 
request (FC_WRITE) but not a mixture of the two. 


Clears the FcASY_READ_QUEUED and FCASY_WRITE_QUEUED bits in fcasy. flags. 


If active.stat 1S TRUE (indicating an error), it sends itself an ao_cancEeL message. This closes the file on 
detection of a read or write error (read errors include z_F1LE_EOoF); in the case of a write it ensures that the 
partially written file is deleted. 


Sends itself an rc_REQUEST_comp message before returning RUN_ACTIVE_USED. 


& FA_CLOSE Close the file 


VOID fa_close (VOID) ; 


Close the file by supersending an ra_cLosE message. Sets fcasy.recvname (which is used on detection of 
an error to delete any partially written file) to nuLL. 


& FC_OPEN Open a file 


INT fc_open(TEXT *name, INT mode, FCOPY_DISP *pdinfo) ; 


Open the file with name in the buffer pointed to by name (which must be at least p_rwames1ze bytes long) 
in the specified mode and fill in the struct at pdinfo with as much information as possible about the file. 
The items that have been written to *pdinfo are indicated by the corresponding flag bits being set in 
pdinfo->flags. 


It is assumed that the file is to be opened for either reading or writing, but not both. The value of mode 
must include one of p_roPEN, P_FCREATE Of P_FREPLACE (otherwise the method returns &_GEN_aRG). 


Sets pdinfo->sfname tO name and then parses name (using p_fparse) to ensure that the file name is valid. 
If the file is opened for writing and the specified directory does not exist, it is created automatically. 


If the file is to be opened for reading (mode includes p_ropen), the file size and last modification date are 
written to pdinfo->sfsize and pdinfo->sfdate respectively. Depending on whether the file type is 
binary or text, pdinfo->sftype 1s set to P_FSTREAM Or P_FTEXT. The value of mode is augmented by oring 
in p_rsuare. If the file type is text, mode is converted to use P_FSTREAM_TEXT (rather than p_FTExT) to 
optimise the reading of the file. 


If the file is to be opened for writing the method will return an error if mode includes p_rcreatE and the 
file exists or if mode includes p_FREPLACE and name specifies a directory file. Otherwise pdinfo->rfname iS 
set to name and the value of mode is augmented by oring in p_ruppate. If the file is opened successfully 
fcasy.recvname 1S set to name. The data space pointed to by name must therefore be preserved until the file 
has been closed. 


Returns zero if successful, otherwise a negative error number. 


14 - 13 


OLIB REFERENCE 


Deferred FCASY methods 


FC_REQUEST COMP Inform of completion 


VOID fc_request_comp (VOID); 


A deferred method, called from within the ao_run method, indicating that the read or write request has 
completed. 


If there was a read or write error, the file will already have been closed and, if appropriate, deleted by 
means of an ao_cANcEL message. The subclass is, however, responsible for checking the completion status 
(active.stat) and performing any additional error handling. 


In the absence of such errors, the user is responsible for continuing the operation by sending the next 
AO_QUEUE Of FC_WRITE message. 


Errors in this method should result in p_leave being called. 


FCSYNC 


ACTIVE FACTIVE FCASY FCSYNC 
q 


recvname 


priority flags 


isactive 
pcb 
stat 


destroy ao_cancel ao_queue 


ao_init ao_run fc_write 


2 Soe 
ao_abrun fa_close 
fe-write 


fc_open 


fc_request_comp 


The rcsync abstract class subclasses rcasy. It converts rcasy to use synchronous file read and write 
services, otherwise it is identical to Fcasy. 


As with Fcasy, it is assumed that an instance of a subclass of rcsync is used to either read from or write to 
a file. 


Since file access is synchronous, it should only be used in situations where the read and write operations 
are guaranteed to complete quickly. Thus, it is effectively restricted to use with files on the local filing 
system. 


Class definition 
Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS fcesync fcasy 
Synchronous file I/O for local file system 


{ 


REPLACE ao_queue Synchronous file read 
REPLACE fc_write Synchronous file write 
} 

Property 


None. 


14-14 


14 FILE ACTIVE OBJECTS 


FCSYNC methods 
& AO_QUEUE Read request 


INT ao_queue(UBYTE *buf, UWORD *plen); 


Perform a synchronous read of *pien bytes into but from the file whose channel handle is in active.pcb 
by supersending the ao_quEvE message and then waiting (with p_waitstat) ON active.stat for the read 
to complete. 


Sends itself an ao_cancet (which closes the file and sets active.stat to E_FILE_CANCEL) if the read 
completes with an error. In particular, since =_FILE_EoF is not distinguished from other errors, the file 
will be closed automatically on reading to the end of the file. 


On exit active.isactive and fcasy.flags are both guaranteed to be zero. 


Returns the value of active.stat. 


& FC_WRITE Write request 


INT fc_write(UBYTE *buf, UINT len); 


Perform a synchronous write of 1en bytes from bur to the file whose channel handle is in active.pcb by 
supersending the rc_wRITE message and then waiting (with p_waitstat) ON active.stat for the write to 
complete. 


Sends itself an ao_cance. (which closes and deletes the file, and sets active.stat to E_FILE_CANCEL) if the 
write completes with an error. 


On exit active.isactive and fcasy.flags are both guaranteed to be zero. 


Returns the value of active.stat. 


14-15 


CHAPTER 15 


FILE Lists 


The classes described in this chapter are concerned with the navigation of the directories of a filing system 
and with the generation and storage of directory and file name lists. 


Precursors 


The reader is assumed to understand: 
e active objects and the rnopE and Fscawn abstract classes 
e the vastR and vaxvar variable array classes 
e the file server node, device, directory and file services 
e the p_enter and p_leave error handling services 


Class diagram 


ra ros sitet de fi ae ti ws 
¢ Varoot / ¢ active / 
ly ) mS 
x f e f _ 
Pore ee ‘ 
¢ Vafix / ¢ factive / 
~“ ) 
a _ ) 


min — are a ‘Se 


f Rey oe? Peay 
¢ Vaflat /  , vastr / ¢ sh j Va “ {node ? 


es ue N i 


pres 
a vaxvar 


oe 
a ee Pale, 


y pselvar / ¢ Pnode / 
ee ee 
ae San 


15-1 


OLIB REFERENCE 


PSELVAR 


nrec ke rlen gran 
nspc 


destroy arepta i atest 
va_count va_compress | va_copy 
va_delete a—detetem va_reclen 
va_sort Farinsertm va_replace 


va_key va_capacity | va_init 


va_findisgq Lad va_prec va_deletem 
va_insertisq oe ES va_insertm 
va_append b va_pbuf 
va_insert 

va_search 

va_compare 

va_reset 

Wartest 


The psetvar class subclasses the vaxvar variable array class. It is intended to be used to store an ordered 
array of file and directory names and the additional method is tailored to the special sorting schemes 
needed. 


This class is defined specifically for use by the pset class, described later. The va_test method assumes 
that varoot .key.desc specifies ascending or descending order as normal for the variable array classes, 
but that varoot.key.fold contains one of the psEL_ORDER_xxx values defined below. The 

varoot .key.ofs and varoot .key.1len fields are not used. 


The psEL ps_order method writes directly to the varoot .key.desc and varoot .key. fold fields of its 
component instance of psELvar (as an alternative to providing psELvaR with a subclassed va_key method). 


Each psE.var record is assumed to be an Rc_vaxvar struct, whose buf field points to an allocated heap 
cell containing a psEL_REc struct. The contents of this struct are determined by the owning ese. The 
name field contains either a file name or a directory name. Note that the namien field contains meaningful 
data only if the names are ordered by extension. 


Class definition 
Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS pselvar vaxvar 
Holds the files/dir names in order - dir names first then file names 
{ 
REPLACE va_test 
CONSTANTS 
{ 
PSEL_FLAG_TAG Oxl 


PSEL_ORDER_NAME 0 Order by name alphabetically (default) 
PSEL_ORDER_TIME al Order by time of creation 
PSEL_ORDER_DATE 2 Order by date of creation 
PSEL_ORDER_SIZE 3 Order by size of file 
PSEL_ORDER_EXT 4 Order by extension 
} 
TYPES 
{ 
typedef struct 
{ 
UWORD flags; Tagging flags info 
UWORD namlen; Offset in name of extension 
P_INFO info; File info 


UBYTE name[P_FNAMESIZE]; Max file name size buffer 
} PSEL_REC; 


} 
Property 


None. 


15 -2 


15 FILE LISTS 


PSELVAR methods 
& VA_TEST Compare two records by pointer 


INT va_test (RC_VAXVAR *precl, RC_VAXVAR *prec2); 


Compare the two records pointed to by preci and prec2, returning 0 if the two records are equal, <0 if 
*precl is before *prec2, or >0 if *preci is after *prec2 


Each record is assumed to be an Rc_vaxvar struct whose buf field points to a PSEL_REC struct containing 
either a file name or a directory name. 


A directory name is always ordered before a file name and directory names are always ordered 
alphabetically. 


File names are ordered by one of name, creation time, creation date, size or extension, depending on the 
PSEL_ORDER_XXx value stored in varoot .key. fold. 


The result of the comparison is reversed if varoot .key.desc is non-zero. 


PNODE 


ACTIVE FACTIVE FNODE 
q 


owner flags 
priority pname 
isactive oldname 
pcb pcb 
stat 


destroy fea-etese fnulist ao_abrun 


ao_init ao_queue fn_end_list 
ao_cancel | ao_run fn_nodename 
aerab run fa_close 


The pnove class subclasses the FNopE node and device list generator. 


It is defined specifically for use by the psEt class, described later. The code contains assumptions that the 
owner (whose handle is in factive.owner) is an instance of a subclass of pszEL and makes direct calls to 
PSEL code. 


The prope methods are designed only to be called via the mechanisms provided within the methods of the 
PSEL Class, described later in this chapter. 


Class definition 


Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS pnode fnode 
Used by psel to generate the node/directory array 
{ 
REPLACE ao_abrun 
REPLACE fn_end_list 
REPLACE fn_nodename 
} 


Property 


None. 


15 -3 


OLIB REFERENCE 


PNODE methods 


AO_ABRUN Handle error 


VOID ao_abrun (VOID) ; 


Supersend the ao_aprun message and then make a direct call to reset property and component objects of 
the owner (assumed psEt). 


FN_END LIST Handle completed list 


VOID fn_end_list (VOID) ; 
Process the completion of the node: :device:\ name list. 


Reads and modifies the property of the owning (PsEL) object to indicate that the list has been changed, 
and starts the generation of the file list corresponding to the selected, or the default, item in the 
node: :device:\ list. 


FN_NODENAME Process a list item 


VOID fn_nodename (VOID) ; 
Process a generated node: :device:\ name. 


Makes a direct call to add the generated name to the owner's (psEL) directory/node name list and then 
sends itself an Ao_QUEUE message to continue the scan. 


PSEL 


ACTIVE FACTIVE FSCAN 
q 


owner pfile 
priority pdir 
isactive pnode 
pcb dirent 
stat flags 
ascent 
dirnum 
setpath 
builderr 
fck 
fspec 


fs_matchname ao_init 


fs_fscan ao_abrun 


ao_queue ao_cancel 

ao_run fs_filename 

fa_close fs_dirname 
fs_fscan_end 
ps_get_file 
ps_ascend_path 
ps_descend_path 


fs_end_dirlist ps_set_path 


ps_sense_filename 
ps_select_direntry 
ps_drives 
ps_settag 
ps_gettag 

ps_order 


ps_new_list 


15-4 


15 FILE LISTS 


PSEL is an abstract subclass of rscan, providing methods to navigate a filing system and to generate both a 
node list and a file name list from a wildcard file specification. In addition it provides methods to tag 
items in its file name list and to retrieve such tagged items. 


The node list contains device names or directory names at some specified level. The file name list contains 
files and subdirectories within one particular item in the node list. 


Although psx uses a number of active object components, it appears to a user as a single active object. A 
queued request starts the building of one or more of its lists. On completion it reports: 


e which lists have been changed 
e whether the file specification has changed 


e whether the file name list was either built successfully or was left empty because the physical 
device does not exist (no disk in drive). 


A subclass of psex is used, for example, to generate and navigate the file lists displayed in the file 
commands of the Series 3 System application, and in the MC File Manager application. 


Subclasses of psEL are not expected to replace any of the supplied methods. 


Note that there is no automatic detection of filing system changes. This means that a file list will be out of 
date if, for example, another process has created a file in the directory being displayed after the file list 
was last built. A regeneration of the file name list may be forced by sending a ps_sET_PATH message. 


Class definition 


Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS psel fscan 
Builds a node/directory array and a file array from a wild card path 
{ 
REPLACE ao_init 
REPLACE ao_abrun 
REPLACE ao_cancel 
REPLACE fs_filename 
REPLACE fs_dirname 
REPLACE fs_fscan_end 
DD ps_get_file 
ps_ascend_path 
ps_descend_path 
ps_set_path 
ps_sense_filename 
ps_select_direntry 
ps_drives 
ps_settag 
ps_gettag 
DD ps_order 
DEFER ps_new_list 


D 
D 
D 
D 
D 
D 
D 
D 


pPppprprprpr pe 


CONSTANTS 
{ 
PSEL_RESET_DIR_ARRAY 0x01 True if NOT reset node/dir array 
PSEL_RESET_FILE_ ARRAY 0x02 True if NOT reset files array 
PSEL_RESET_FSPEC 0x04 True if NOT reset fspec[] 
PSEL_DEVICE_ARRAY 0x10 Building device list 
PSEL_DIR_ARRAY 0x20 Building dir list 
PSEL_FILE_ ARRAY 0x40 Building file list 
PSEL_DESCEND 0x80 Building due to a descend 
PSEL_ASCEND 0x100 Building due to an ascend 
PSEL_SETPATH 0x200 Building due to a set path 
PSEL_INIT 0x400 Building due to an init 
PSEL_SELDIR 0x800 Building due to select dir 
PSEL_ANOTHER_CMD 0x1000 
PSEL_GENERATE_DEF 0x2000 
PSEL_QUEUED_CMD 0x4000 Running a queued cmd 
PSEL_CURRENTLY_BUSY (0x100|0x80|0x400|0x200|0x800) 
PSEL_SET_TAG = 
PSEL_CLEAR_TAG 0 
PSEL_TOGGLE_TAG 1 


} 


15-5 


OLIB REFERENCE 


PROPERTY 3 
{ 
PR_PSELVAR *pfile; File name lists 
PR_VASTR *pdir; Directory/Node name list 
PR_PNODE *pnode; Node List Generator 
UWORD Which directory in list should be highlighted 


UWORD 
UWORD 
UWORD 


File selector control flags 


UBYTE *setpath; 


WORD builderr; 
P_FPARSE fck; 


Files list build error to report 
Currently cracked wildcard file spec 


TEXT fspec[P_FNAMESIZE]; Current wildcarded file spec 


} 
} 


Property 


psel. 


psel. 


psel. 


psel. 


psel. 


psel. 


psel. 


psel. 


psel. 


psel. 


psel. 


15 - 6 


pfile 


pdir 


pnode 


dirent 


flags 


ascent 


dirnum 


setpath 


builderr 


fck 


fspec 


the handle of an instance of pszLvar, which holds the file name list in an 
array of psEL_ReEc records. A subclass may access this handle, and will 
typically pass it to display code. (Note that pszLvar's va_pBur method 
returns a pointer to a PSEL_RECc struct, rather than to the text of a file 
name.) 


the handle of an instance of vastr, which holds the array of names for a 
node or directory list. A subclass may access this handle and will typically 
pass it to display code. 


the handle of an instance of pNopz, which generates a node: :device:\ 
name list. It should not be accessed by a subclass. 


the index of the current node list item in the psel.pdir VASTR array. It 
defines the subdirectory for which the file list is built (a value of -1 
indicates that no entry is current). A subclass may read this field to 
indicate which displayed node list entry to highlight. 


controlling flags used to drive the psx object. A subclass may read the 
values of the pSEL_RESET_DIR_ARRAY, PSEL_RESET_FILE_ARRAY and 
PSEL_RESET_FSPEC bit-fields. 


the outstanding number of directory ascends to be performed (a user may 
request multiple ascends faster than they can be serviced). It should not be 
accessed by a subclass. 


the index of the most recently selected entry from the psel.pdir VASTR 
array. Typically the user interface will allow the selection of a new entry 
from this array while eset is busy building the file names array for a 
previously selected entry. It should not be accessed by a subclass. 


a pointer to the most recently selected wildcarded file name specification 
from which the node and file name arrays are to be built. The data space 
to which it points must be preserved until the arrays have been fully built. 
It should not be accessed by a subclass. 


an error number corresponding to a drastic error (such as out of memory, 
or the removal of a filing system) which occurred while building the node 
and file name arrays. If no error has occurred the value will be zero. A 
subclass is expected to test this value to determine the build completion 
result when the deferred ps_new_List method is called. 


the parsed file name information for the wildcarded name (contained in 
psel.fspec) that is currently being used to build the node and file name 
arrays. A subclass should treat this as a read-only field. 


the wildcarded file name specification that drives the generation of the 
node and file name arrays. Typically this field could be used to display the 
full file name specification corresponding to the arrays that have just been 
built. A subclass should treat this as a read-only field. 


15 FILE LISTS 


PSEL methods 


A user is expected to send only those explicit messages that appear in the following list: 


PS_ASCEND_PATH ascend one subdirectory level 
PS_DESCEND_PATH descend to a subdirectory 
PS_SET_PATH set a new path 
PS_SENSE_FILENAME sense a file list item 
PS_SELECT_DIRENTRY select a node list entry 
PS_DRIVES ascend to the drives level 
PS_SETTAG set/clear a file tag 

PS_GETTAG get a tagged file 

PS_ORDER set the file list order 

The remaining methods are intended for internal use. 
Many of the above methods cause either or both of the directory/node and file name lists to be rebuilt. If 


this fails (say, because the pack has been removed or the filing system no longer exists) then the lists are 
rebuilt at the node: :device:\ level. All such methods result in a (deferred) ps_NEw_LIsT message being 
sent. Depending on whether rebuilding is required, this message may be sent either before the method 
returns or at some later time, when building is complete. 


AO_INIT Initialise 


VOID ao_init (TEXT *pname) ; 


Supersends an ao_1n1T message to add itself to the appman queue and then creates and initialises the 
psel.pdir, psel.pfile (with a granularity of 32) and psel.pnode components. 


Then starts building the node and file name arrays, using the text pointed to by pname as the initial file 
name specification. 


If the initial file specification is not valid (say, because the filing system no longer exists) the default lists 
are built. These consist of: 


e anode list containing all currently available node: :device:\ names 


e a file name list for the directory indicated by the first item in the node list, containing all files 
that match the initial file name specification. 


Calls p_leave on error (out of memory). 


AO_ABRUN Handle error 


VOID ao_abrun (VOID) ; 
Handle an error arising during the processing of an ao_RUN message. 


Discards the contents of the node and file name lists (at least one of which is likely to be only partially 
built) and sets psel. fspec to contain a null string. 


Sends a ps_NEW_LIST message, which will normally cause the user interface to display empty lists and 
then supersends the ao_aBRuN message. 


This method will only be invoked by out of memory errors or by the disappearance of filing systems 
during the generation of the lists. 


& AO CANCEL Cancel list building 


VOID ao_cancel (VOID); 


Sends an ao_cAaNCEL tO psel.pnode to cancel any request on the node list generator and then supersends 
an AO_CANCEL to cancel any file scan request. These two messages ensure that any open channels are 
closed. Following this, the contents of the node and file name lists are discarded. 


This method is intended only to be executed as a consequence of psEL receiving a DESTROY message. A 
user should not, for example, send an ao_caNcEL message when requesting an operation (such as an 
ascend) before a previous operation has completed. Such a sequence is handled by pset's internal logic 
and the user should simply request the new operation. 


15-7 


OLIB REFERENCE 


FS_FILENAME Add a file name 


VOID fs_filename (VOID) ; 
Add a file name to the file name list. 


Generates a psEL_rec for the file name pointed to by fscan.pname and appends it to the file name list (the 
list will be ordered when it is complete). 


Note that, to minimise memory use, the psEL_REc struct is adjusted to the exact length required for its 
content before it is appended. You should also be aware that the contents of the namien field of the 
PSEL_REC Struct will only be valid if the file name list is sorted by extension. 


If the name is added successfully, sends an ao_quEUE message to continue the scan. 


May call p_leave (E_GEN_NOMEMORY) . 


FS DIRNAME Add a directory name 


VOID fs_dirname (VOID) ; 


Add a directory name to either the node list or the file name list depending on which list is currently being 
built. 


If the name is being added to the node list, the full name (taken from the start of the fscan.name buffer) is 
inserted in alphabetical order. 


If it is being added to the file name list, only the ‘file name' part (pointed to by fscan.pname) is appended 
to the list exactly as described for the f£s_filename method. 


If the name is added successfully, sends an ao_quzuE message to continue the scan. 


May call p_leave (E_GEN_NOMEMORY) . 


FS FSCAN_END Process end of a scan 


VOID fs_fscan_end(VOID) ; 
Process the end of the building of either the node list or the file name list. 
If the node list has just been built, the building of the appropriate file name list is started. 


If the node list has not changed (say, because the build was initiated by a directory ascend request when 
already at the drives level), the processing is as for the completion of the building of the file name list, 
described below. 


If the file name list has just been built, a check is made to see if any additional requests (such as one or 
more directory ascends) have been made while the list was being built. If so, the appropriate list building 
is restarted. Otherwise, provided the file name list has changed, it is sorted in the currently specified order 
and a ps_NEW_LIST message is sent to indicate that list building is complete. 


PS GET _ FILE Build file name list 


INT ps_get_file (VOID); 


Discard the current file name list and send an rs_rscan message to start a scan to build a new list for the 
directory specified by the current item in the node list. The list will include all subdirectories, together 
with all file names that match the wildcard file name and extension string contained within the full file 
specification in the psel. fspec buffer. 


Returns zero, indicating a successful start of the scan. 


Calls p_1eave on error. 


15-8 


15 FILE LISTS 


& PS ASCEND PATH Ascend one subdirectory level 


VOID ps_ascend_path (VOID); 


Start the rebuilding of the node and file name lists for a directory level one higher than that specified by 
the wildcarded full file specification in pse1.fspec. 


If the current directory level is at the node: :device:\ level already (if, for example, psel.fspec contains 
"LOC::A:\*.1MG") then no further ascends can be made. The node list will, however, be re-built because a 
filing system may have been added or removed since the last time the lists were built. This is the only way 
in which such a change in the filing system can be recorded in the node list. 


In such a case the files list will not be re-built unless the current node has disappeared. 


If this message is received while the lists are in process of being built then the ascend request will be 
stored internally. On completion of the current build, building will be restarted (without sending a 
PS_NEW_LIST message) at the new directory level. 


& PS DESCEND PATH Descend to a subdirectory 


VOID ps_descend_path(UINT entryno) ; 


Descend into the subdirectory specified by record number entryno in the file name list and start the 
rebuilding of the node and file name lists. 


Does nothing if the lists are currently being built (since the array from which the entry was selected no 
longer exists). 


An entryno of -1 (meaning that no list item was selected) has the same effect as a value of 0, specifying 
the first item. 


The file name list is checked to ensure that it contains the entry number specified and that the 
corresponding record is the name of a directory. If either of these tests fail the method does nothing. 


Otherwise the node and file name lists are rebuilt for the new directory level. 


& PS SET PATH Set a new path 


VOID ps_set_path(TEXT *pname) ; 


Start the rebuilding of the node and file name lists to correspond with the wildcard full file specification 
pointed to by pname. 


If the lists are currently being built, the new path name pointer is stored until the appropriate time that the 
current build can be abandoned and a new build started. 


In all cases the data space pointed to by pname must be preserved until a ps_NEW_LIST message is received 
to indicate that the lists have been rebuilt. 


& PS SENSE FILENAME Sense a file list item 


INT ps_sense_filename (INT entryno, PSEL_REC **pprec) ; 
Write, to *pprec, a pointer to the pszEL_ReEc data for the file list item with record number entryno. 


Returns zero if successful. Does not write to *pprec and returns E_FILE_LOCKED if the list is currently 
being built. 


& PS SELECT DIRENTRY Select a node list entry 


VOID ps_select_direntry (INT entryno) ; 
Start the building of the file name list for the directory specified by item number ent ryno in the node list. 


If a file name list is currently being built as a result of an earlier ps_sELECT_DIRENTRY message, the 
current activity is aborted and the build is restarted for the new list. This provides a rapid response to 
repeated ps_SELECT_DIRENTRY messages received from the user interface (generated, for example, as the 
user moves a highlight up and down a displayed list). If a list is being built for any other reason, the 
PS_SELECT_DIRENTRY message has no effect. 


15-9 


OLIB REFERENCE 


© PS DRIVES Ascend to the drives level 


VOID ps_drives (VOID) ; 


Start the rebuilding of the node and file name lists to generate a node list containing node: :device:\ names 
and a file name list containing those items which match the file name and extension contained in the 
wildcarded full file specification in the psel. fspec buffer. 


Does nothing if the lists are currently being built. 
If the lists are currently at the drives level then they are not rebuilt. 


In either case a PS_NEW_LIST message will be sent to indicate that the list building is complete. 


& PS _SETTAG Set/clear a file tag 


INT ps_settag(INT entryno, INT flag); 


Set, clear or toggle the tag status (held in the flags field of the pszL_rxEc struct) of the file name list item 
specified by entryno. 


The tag status will be set if f1ag is ps—EL_sET_TAG, Cleared if f1ag is PSEL_CLEAR_TAG and toggled if flag 
iS PSEL_TOGGLE_TAG. 


Returns True if the tag status has been set, and rause if it has been cleared. 


& PS _GETTAG Get a tagged file 


INT ps_gettag(INT index, PSEL_REC **pprec) ; 


Write, to *pprec, a pointer to the psEL_REc of an item in the file name list that has its tag status set, and 
return either a (positive) value to be used as the index for a subsequent ps_GETTAG message, or 
E_FILE_EOF if there are no further tagged entries. 


If index is zero, the value written to *pprec points to the first tagged item. If index is the value returned 
by the previous ps_cettac the value written to *pprec is a pointer to the next tagged item. 


This method allows the extraction of the names of all tagged files, one by one. 


PS ORDER Set the file list order 


VOID ps_order(INT mode, INT reverse); 


Set the current file name list order and sort the entries. The value of mode should be one of: 


PSEL_ORDER_NAME order alphabetically by full name (the default) 
PSEL_ORDER_TIME order by time of creation 

PSEL_ORDER_DATE order by date of creation 

PSEL_ORDER_SIZE order by size of file 

PSEL_ORDER_EXT order alphabetically by extension 


If reverse is TRUE the ordering is reversed. 


The current file name list is regenerated in the new order. If the ordering is not by extension the 
reordering will be completed before this method returns. Otherwise the method starts a build of the file 
name list in the specified order and this will complete at some future time. In either case an ps_NEW_LIST 
message is sent when the list is complete. 


All subsequent builds of the file name list will be performed in the specified order, until it is changed by a 
further ps_oRDER message. 


By default the file name list is built in ascending alphabetical name order. 


15 - 10 


15 FILE LISTS 


Deferred PSEL methods 
& PS NEW _LIST Process the completion of list building 


VOID ps_new_list (VOID) ; 


A deferred method which is always received on completion of any request to build or reorder the node 
and/or file name arrays. It may be received either before the build request returns or at a later time, 
depending on whether any lists need to be rebuilt. 


The supplier of this method is expected to test psel.blderr to determine the result of the build, and may 
also read psel.flags, psel.pfile, psel.pdir, psel.dirent, psel.fck and psel.fspec, aS explained in 
the descriptions of the property fields. 


A typical action would be to regenerate the data displayed in the user interface. It should examine 
psel.flags and: 


e if PSEL_RESET_DIR_ARRAY iS FALSE, regenerate the display of the directory/node names from the 
psel.pdir array 


e if PSEL_RESET_FILE_ARRAY iS FALSE, regenerate the display of the file names from the 
psel.pfile array 


e if PSEL_RESET_FSPEC iS FALSE, regenerate the display of the file name specification from the 
psel.fspec buffer 


This method is expected to return. Any code that may result in p_leave being called must be run under 
the protection of p_enter. 


15-11 


CHAPTER 16 


FILE MANAGEMENT CLASSES 


The classes described in this chapter, and in particular the rman class, supply the basic engine for 
performing file management. They provide a set of high-level file system operations, for example, to copy 
a set of files, delete a directory structure or format an SSD. 


FMAN creates and uses component instances of the FMMK, FMFMT, FMSCAN, FMSRC and FMTARG active object 
classes (which are all subclasses of FACTIVE). These components do the bulk of the work and, by breaking 
a potentially lengthy operation into small sections, ensure that the application remains responsive to 
window server events. Note that only one of these components is active at any one time. 


The classes are strongly interdependent. rman reads from and writes to the property of the other classes, 
which themselves rely on their being owned components of Fuan. 


Precursors 


The reader is assumed to understand: 
e the active object scheduling mechanisms in the application manager 
e the FACTIVE, Fscan and Fcasy classes 
e the PLIB file system services 
e =the p_enter and p_leave error handling services 


Class diagram 


tee 
¢ active / 
a me 
= 
ie factive 
cee AES “y 
ez ) 
-, aa ae _ to —~ ze 7 ae ) 
wo —— Te ie rea 
Gas M t Gataee Se fmscan / 
= ) 
err 


16-1 


OLIB REFERENCE 


FMAN 


srcfile 


targfile 


fmscan 
fmmk 
fmfmt 
action 
mode 


fman_init 
fman_cancel 
fman_copy 


srclen 
dispinfo 
targname 
wildsrcname 
wildtargname 
buf 


fman_name 
fman_info 


fman_attrib 


fman_delete 
fman_rename fman_complete 
fman_make fman_newname 
fman_remove fman_update 
fman_copydev fman_fileexist 


fman_format fman_error 


The rman (file manager) abstract class provides a set of file management operations. It must be subclassed 
to supply the deferred methods (which are chosen to provide a flexible interaction with any user interface) 
in order to create a useful object. It is not expected that a subclass will replace any of the supplied 
methods. 


An FMaN operation is initiated by sending the appropriate message from the following list: 


FMAN_COPY copy files 

FMAN_DELETE delete files 

FMAN_RENAME rename files 

FMAN_MAKE make a directory 

FMAN_REMOVE remove a directory (and its subdirectories) 
FMAN_COPYDEV copy a device 

FMAN_FORMAT format a device 

FMAN_NAME name a device 

FMAN_ATTRIB set file attributes 


Each of these methods will call p_1eave on error. If successful in initiating the required action, some of 
these methods return zero, while others call p_1eave (0) (to simplify the centralisation of error handling). 
It is therefore essential to send these messages under the protection of a p_enter (you could, for example, 
send the message by means of p_entersena). Under such protection the methods which call p_1eave (0) 
will behave equivalently to those methods which return zero. 


Any operation may complete before the send of the initialising message has returned. Normally, however, 
each of these operations will involve at least one active object (typically rmscan) which at some future 
time will be sent at least one ao_run message. Thus the operation will usually complete long after the send 
of the initiating message has returned. 


Regardless of when it occurs, the completion may represent the successful conclusion of the operation, or 
may result from the operation being cancelled, either at the user's request or as the result of an error 
condition. Every completion, for whatever reason, results in the subclass of rman receiving one, and only 
one, FMAN_COMPLETE message. This is typically used to destroy any visual indicator of the current 
operation that is being presented to the user. 


16-2 


Class definition 


16 FILE MANAGEMENT CLASSES 


Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS fman root 
The File Manager 
{ 
ADD fman_init Create/Init the active objects 
ADD fman_cancel Cancel the last request 
ADD fman_copy Copy files 
ADD fman_delete Delete files 
ADD fman_rename Rename files 
ADD fman_make Make a directory 
ADD fman_remove Remove a dir structure 
ADD fman_copydev Copy a device 
ADD fman_format Format a device 
ADD fman_name Name a Pack 
ADD fman_info=p_dummy For define of O_FMAN_INFO at least 
ADD fman_attrib Set file attributes 
DEFER fman_complete Operation now complete 
DEFER fman_newname Operation now on this file(s) 
DEFER fman_update Update copying display 
DEFER fman_fileexist Destination file exists 
DEFER fman_error Error in operation, abort/continue 
CONSTANTS 
{ 
FMAN_READ_SIZE 0x800 Copy 2k at a time 
FMAN_COPYING 0 
FMAN_DELETE 1 
FMAN_RENAME 2 
FMAN_MAKE 3 
FMAN_REMOVE 4 
FMAN_FORMAT 5 
FMAN_NAME 6 
FMAN_ATTRIB 7) 
} 
PROPERTY 5 
{ 
PR_FMSRC *srcfile; Src/Read file active object 
PR_FMTARG *targfile; Target/Write file active object 
PR_FMSCAN *fmscan; File system scan active object 
PR_FMMK *fmmk; Make Dir active object 
PR_FMFMT *fmfmt; Format a pack. 
UWORD action; Current file manager action 
UWORD mode; Current file create/replace mode 
UWORD srclen; 
FCOPY_DISP dispinfo; Display info 
UBYTE targname [P_FNAMESIZE]; Fully spec'ted target name 
UBYTE wildsrcname[P_FNAMESIZE]; Entered wildcarded srcname 
UBYTE wildtargname[P_FNAMESIZE]; Entered wildcarded target 
UBYTE buf [FMAN_READ_SIZE]; 
} 
} 
Property 
fman.srcfile the handle of an instance of rusrc, representing the source file during a 
file copy. It should not be accessed by any subclass. 
fman.targfile the handle of an instance of rmtare, representing the target file during a 
file copy. It should not be accessed by any subclass. 
fman. fmscan the handle of an instance of rmscan, used to generate the lists of files upon 
which an operation acts. It should not be accessed by any subclass. 
fman. fmmk the handle of an instance of rmmx, used to create a directory structure. It 
should not be accessed by any subclass. 
fman. £mfmt the handle of an instance of rvrut, used to format an SSD. It should not 


be accessed by any subclass. 


16 -3 


OLIB REFERENCE 


fman.action the current file manager action, used to determine what operation to 
perform on a name generated by rmscan. It takes one of the following 
values: 


FMAN_COPYING - copying files 

FMAN_DELETE - deleting files 

FMAN_RENAME - we are renaming files 
FMAN_ATTRIB - Changing the file attributes 
FMAN_MAKE - creating a directory structure 
FMAN_REMOVE - removing a directory structure 
FMAN_FORMAT - formatting an SSD 

FMAN_NAME - naming an SSD 


It should not be accessed by any subclass, but see also fman.dispinfo, 
which also contains this data. 


fman.mode the current create/replace mode for a file copy operation, At the start of a 
copy it is set to create the copy file(s) but may later be modified, 
depending on the result of an rMaN_FILEEXxIsT message. It should not be 
accessed by any subclass. 


fman.srclen how many bytes to read from a source file, and the length of buffered data 
to write to a target file. It should not be accessed by any subclass. 


fman.dispinfo information describing the current file manager action (see the 
fman_newname method for details of the rcopy_p1sp struct). It is intended 
to be used to provide information about the current operation for the user 
interface. It should only be read from within the fman_newname method. 


fman.targname the generated full file specification of a target file. It should not be 
accessed by any subclass. 


fman.wildsrcname the wildcarded file name passed as the source file name in one of the 
messages that initiates an operation. It should not be accessed by any 
subclass. 

fman.wildtargname the wildcarded file name passed as the target file name in one of the 


messages that initiates an operation between two files. It should not be 
accessed by any subclass. 


fman.buf the data read from the source file and written to the target file during a 
file copy. It should not be accessed by any subclass. 


FMAN methods 


FMAN_INIT Initialise the file manager 


VOID fman_init (VOID) ; 


Create and initialise the five active objects whose handles are stored in the first five items of rman's 
property. The initialisation of each registers rman as its owner and adds the active object to the application 
manager's active object task queue. 


Calls p_1leave (E_GEN_NOMEMoRy) on failure. 


FMAN_CANCEL Cancel an outstanding request 


VOID fman_cancel (VOID) ; 


Cancel any current file operation, sending ao_cANCEL messages to the appropriate active object 
components, depending on the value of fman. action. 


Following this, an FMAN_COMPLETE message Is sent to indicate that the current operation has been 
completed. 


16-4 


16 FILE MANAGEMENT CLASSES 


FMAN_COPY Copy files 


VOID fman_copy(UBYTE *src, UBYTE *targ, INT flags); 


Start the copy of files specified by the wildcarded source file name at src to the wildcarded target name at 
targ. 


Before the copy is started, the source and target file names are validated: 


e The source file name must not be a null string and it must be a name acceptable to the p_fparse 
function (the name is parsed with "*" as the related name and the resulting full file specification 
is written into fman.wildsrcname). 


e If the target name is a null string, it is replaced by the file name and extension taken from the full 
file specification in fman.wildsrcname. The target name is parsed with a nux related name into 
fman.wildtargname. A final check is made that the resulting source and target file names are not 
identical. 


If the validation generated the target name from the source name (because targ points to a null string) the 
name and extension in fman.wildtargname are replaced by "*". 


Following this, fman.dispinfo.protocol and fman.action are both set to rman_copyinec and 
fman.dispinfo.blksiz iS set tO FMAN_READSIZE, With fman.dispinfo. flags set to indicate that the 
appropriate fields are valid. 


The value of fman.mode 1s Set to P_FCREATE|P_FSTREAM, SO that, initially, the copy files will be created (as 
opposed to, say, replacing existing files). 


The flags parameter should contain a bitwise combination of one or more of the following values, defined 
in factive. g: 

FS_ALL_FILES include all non-directory files that are neither hidden nor system files 
FS_WRITABLE aS FS_ALL_FILES, but excludes write-protected files (see below) 

FS_HIDDEN include hidden files 

FS_SYSTEM include system files 

FS_DIRECTORIES include directory files 

FS_MODIFIED exclude unmodified files (include only files that have p_ramop set) 
FS_INCLUDE_SUBDIRECTORIES extend the scan to subdirectories 

FS_PARSE_NAME parse file names before reporting them 


The rmscan component has fscan. flags set to the passed flags value, ored with rs_HIDDEN|FS_SYSTEM, 
and fscan.match is set to point to the name and extension within the fman.wildsrcname buffer. An 
FS_FSCAN message is then sent to the rmscan component to generate the list of files to copy. The initial 
start up file name passed with this message is the full contents of fman.wildsrcname. 


Any error encountered during the file name validation or in rMscan's rs_Fscan method results in p_leave 
being called with an appropriate error. 


On successful completion the method calls p_leave (0). The rman_copy message must therefore be sent 
under the protection of a p_enter. 


Further processing of the file copy is handled by the rmscan component. 


FMAN_DELETE Delete files 


VOID fman_delete(UBYTE *src, INT flags); 


Start the deletion of one or more files as specified by the wildcarded file specification string pointed to by 
src. In contrast to the fman_remove method, directories are not deleted. 


Before the deletion is started the file specification string is validated. It must not be a null string and it 
must be a name acceptable to the p_fparse function (the name is parsed with "«" as the related name and 
the resulting full file specification is written into fman.wildsrcname). 


Following this, fman.dispinfo.protocol and fman.action are both set to rMaN_DELETE. The value of 
fman.dispinfo. flags is Set to indicate that the appropriate field is valid. 


16-5 


OLIB REFERENCE 


The flags parameter should contain a bitwise combination of one or more of the following values, defined 
in factive. g: 

FS_ALL_FILES include all non-directory files that are neither hidden nor system files 
FS_WRITABLE aS FS_ALL_FILES, but excludes write-protected files (see below) 

FS_HIDDEN include hidden files 

FS_SYSTEM include system files 

FS_DIRECTORIES include directory files 

FS_MODIFIED exclude unmodified files (include only files that have p_ramop set) 
FS_INCLUDE_SUBDIRECTORIES extend the scan to subdirectories 

FS_PARSE_NAME parse file names before reporting them 


The rmscan component has fscan. flags set to the passed flags value, ored with rs_HIDDEN|FS_SYSTEM, 
and fscan.match is set to point to the name and extension within the fman.wildsrcname buffer. An 
FS_FSCAN message is then sent to the rmscan component to generate the list of files to delete. The initial 
start up file name passed with this message is the full contents of fman.wildsrcname. 


Any error encountered during the file name validation or in rmscan's rs_Fscan method results in p_leave 
being called with an appropriate error. 


On successful completion, the method calls p_leave (0). The rMaAN_DELETE message must therefore be sent 
under the protection of a p_enter. 


Further processing of the file deletion is handled by the rmscan component. 


FMAN_RENAME Rename files 


VOID fman_rename (UBYTE *src, UBYTE *targ); 


Start the renaming of one or more files as specified by the wildcarded file specification string pointed to 
by src to names specified by the wildcarded file specification string pointed to by targ. 


Before the rename is started the source and target file names are validated: 


e The source file name must not be a null string and it must be a name acceptable to the p_fparse 
function (the name is parsed with "*" as the related name and the resulting full file specification 
is written into fman.wildsrcname). 


e If the target name is a null string it is replaced by the file name and extension taken from the full 
file specification in fman.wildsrcname. The target name is parsed with a nut related name into 


fman.wildtargname. 


Final checks are made that the resulting source and target file names are not identical, and that both file 
specifications refer to the same directory (files can not be renamed across directories, devices or file 
systems). 


If the validation generated the target name from the source name (because targ points to a null string), 
the name and extension in fman.wildtargname are replaced by "*". 


Following this, fman.dispinfo.protocol and fman.action are both set to FMAN_RENAME. The value of 
fman.dispinfo. flags is set to indicate that the appropriate field is valid. 


The rmscan component has fscan. flags Set t0 FS_ALL_FILES|FS_HIDDEN|FS_sysTEM and fscan.match IS 
set to point to the name and extension within the fman.wildsrcname buffer. An rs_rscan message is then 
sent to the rmscan component to generate the list of files to rename. The initial start up file name passed 
with this message is the full contents of fman.wildsrcname. 


Any error encountered during the file name validation or in rmscan's rs_Fscan method results in p_leave 
being called with an appropriate error. 


On successful completion the method calls p_1eave (0). The rMaN_RENAME message must therefore be sent 
under the protection of a p_enter. 


Further processing of the file rename is handled by the rmscan component. 


16 - 6 


16 FILE MANAGEMENT CLASSES 


FMAN_MAKE Make a directory tree 


INT fman_make(UBYTE *name) ; 
Start the creation of a directory or directory structure as specified by name (using p_mkdir). 


The values of fman.dispinfo.protocol and fman.action are both set to rman_maxe. The string pointed to 
by name is copied into the fman.targname buffer and fman.dispinfo.sfname is set to point to this buffer. 
The value of fman.dispinfo. flags Is set to indicate that the appropriate fields are valid. 


Following this, the property of the rmmx component is modified directly, setting active.isactive tO TRUE, 
and active.stat to zero. The I/O semaphore is then signalled (by calling p_iosigna1) so that rumx will, 
at some future time, receive an ao_RUN message. 


The method returns zero. 


See the rmx class for details of further processing. 


FMAN_REMOVE Delete a directory structure 


INT fman_remove (UBYTE *name) ; 


Remove the directory structure specified by the name of a directory pointed to by name. The specified 
directory and all included files and subdirectories are deleted. 


The values of fman.dispinfo.protocol and fman.action are both set to rman_remove. The value of 
fman.dispinfo. flags is set to indicate that the appropriate field is valid. 


The passed name is parsed into the fman.wildsrcname buffer and adjusted, if necessary (with the aid of a 
call to p_chdir) to ensure that it contains a valid directory name for the relevant filing system. (For 
MSDOS, for example, it ensures that the directory name includes a trailing '\' character.) This may fail if 
the supplied text does not produce a valid directory name. 


The rmscan component has fmscan.match Set to point to the string "*" (to match all files) and 

fmscan. flags Set tO FS_ALL_FILES|FS_INCLUDE_SUBDIRECTORIES |FS_HIDDEN|FS_SYSTEM So that it will 
generate the names of all the files and directories below the specified directory. Following this, the rmscan 
component is sent an rs_Fscan message. The initial start up file name passed with this message is the full 
contents of fman.wildsrcname. 


Returns zero if the remove has been started successfully, or calls p_leave on error. 


Further processing of the directory removal is handled by the rmscan component. 


FMAN_COPYDEV Copy a device 


VOID fman_copydev(UBYTE *src, UBYTE *targ, INT flags); 


Initiate the copy of the device specified by src to the device and directory name specified by targ, 
reproducing the source device structure under the target directory. This method effectively provides a 
backup service. The results will be unpredictable if src does not point to a device name. 


The value of f1ags should be either zero, to copy all files, or rs_MopDIFIED, to restrict the copy to only 
those files which are marked as modified. 


The values of fman.dispinfo.protocol and fman. action are both set to rMAN_coPyYING, and 
fman.dispinfo.blksiz iS set to FMAN_READ_S1ZE. The value of fman.dispinfo. flags iS set to indicate 
that the appropriate fields are valid. 


The target name is copied into fman.wildtargname, and is converted to a directory name, as in the 
fman_remove method. The source name is parsed into fman.wildsrcname and both names are validated, as 
for the fman_copy method. A further check ensures that the source and target names do not specify the 
same device. 


The value of fman.mode 1s Set to P_FREPACE | P_FSTREAM, SO any previously existing target files will be 
overwritten without notification. 


The rmscan component has fscan. flags Set to the passed flags value, ored with 
FS_ALL_FILES|FS_INCLUDE_SUBDIRECTORIES|FS_HIDDEN|FS_SYSTEM, and fscan.match Is Set to point to 
the string "*". An rs_Fscan message Is then sent to the rmscan component to generate the list of files to 
copy. The initial start up file name passed with this message is the full contents of fman.wildsrcname. 


Any error encountered during the name validation or in rmscan's Fs_Fscan method results in p_leave 
being called with an appropriate error. 


16-7 


OLIB REFERENCE 


On successful completion, the method calls p_1eave (0). The rman_copypEv message must, therefore, be 
sent under the protection of a p_enter. 


Further processing of the device copy is handled by the rmscan component. 


FMAN_FORMAT Format a device 


INT fman_format (UBYTE *devname, UBYTE *volname, UINT flags); 
Initiate the formatting of the device specified by devname, giving it a volume name specified by volname. 


Although there is no intrinsic restriction on the filing system in which the format is to take place, the 
REM:: filing system currently does not support the required formatting services. Thus, an error condition 
will occur if an attempt is made to format a device on the REM:: filing system. 


The value of flags must be either zero or p_rFLowDENstITv. It specifies the format mode for the formatting 
of floppy disks. (This is primarily supplied to support future expansion since, at the time of writing, there 
is no LOC:: floppy disk drive.) 


The passed device name and volume name concatenated into fman.targname and the device is opened for 
formatting with the open file handle written directly to the active.pcb property of the rmrmT component. 


The values of fman.dispinfo.protocol and fman.action are both set to FMAN_FORMAT, 
fman.dispinfo.sfname is set to point to the fman.targname buffer and fman.dispinfo.blksiz Is set to 1. 
The value of fman.dispinfo. flags Is set to indicate that the appropriate fields are valid. 


The property of the rurmt component is further modified, by setting fmfmt . flags to FMFMT_NaME (defined 
by the rmrmt class) active.isactive to TRUE and active.stat to zero. The I/O semaphore is signalled by 
a call to p_iosignal, ensuring that rmrut will eventually receive an ao_RUN message. 


Returns zero if the remove has been started successfully, or calls p_leave on error. 


See the rmrmt class for details of further processing. 


FMAN_NAME Name a device 


INT fman_name(UBYTE *devname, UBYTE *volname) ; 
Change the volume name on the device specified by devname to the name pointed to by voiname. 


This method is exceptional, in that the action is performed synchronously. It will always have completed 
(either successfully or with an error) by the time the method terminates. 


The method returns zero if the device was named successfully, or calls p_1eave with the appropriate error 
number on failure. 


FMAN_INFO Obsolete method 


VOID fman_info (VOID) ; 


This method is no longer in use and is maintained solely to preserve the OLIB user interface. 


FMAN_ATTRIB Set file attributes 


VOID fman_attrib(UBYTE *pname, UWORD attribs, UINT flags); 


Initiate the setting of the file attributes specified by att ribs for the set of files specified by the wildcarded 
name pointed to by pname. 


The value of attribs may take any combination of the following flags: 


P_FAWRITE a writable file (not read only, deletable) 
P_FAHIDDEN a hidden file 

P_FASYSTEM a system file 

P_FAMOD the file is marked as modified. 


Both the set and the clear states of all flags are significant; the clear state has the opposite meaning to the 
set state. For example, if the p_rawr1te flag is not set then the file will be made read only. 


16-8 


16 FILE MANAGEMENT CLASSES 


The value of f1ags must be either nuLt to restrict the operation to the single specified directory, or 
FS_INCLUDE_SUBDIRECTORIES to extend the setting of attributes to files within all subdirectories of the 
specified directory. 


The values of fman.dispinfo.protocol and fman.action are both set to rMAN_ATTRIB and 
fman.dispinfo. flags is set to indicate that the appropriate field is valid. 


The name pointed to by pname must not be a null string. Provided it passes this check, it is parsed (with a 
related name of "*") into £man.wildsrcname, and fman.mode is Set to the value of attribs. 


The rmscan component has fscan. flags Set to the passed flags value, ored with 
FS_ALL_FILES|FS_HIDDEN|FS_SYSTEM, and fscan.match Is Set to point to the name and extension within 
the fman.wildsrcname buffer. An rs_rscan message is then sent to the rmscan component to generate the 
list of files whose attributes are to be changed. The initial start up file name passed with this message is 
the full contents of fman.wildsrcname. 


Any error encountered during the name validation or in rmscan's Fs_Fscan method results in p_leave 
being called with an appropriate error. 


On successful completion the method calls p_1eave (0). The rMaN_ATTRIB message must therefore be sent 
under the protection of a p_enter. 


Further processing of the setting of attributes is handled by the ruscan component. 


Deferred FMAN methods 


& FMAN_COMPLETE Processing completed 


VOID fman_complete (VOID) ; 
Notify that an asynchronous file manager request has now completed. 


This message will not be received if the request failed to start (if, for example, the fman_copy method 
called p_leave with a non-zero parameter). Provided the request started successfully, this message is 
guaranteed to be received, regardless of the reason for the completion. Such reasons include: 


e there are no more files to handle 
e the request was aborted by the user, or otherwise cancelled 
e the request terminated with a non-recoverable error 


Errors in the file manager request are handled (for example, via the FMAN_ERROR and FMAN_FILEEXIST 
messages) prior to receipt of this message and so the fman_complete method does not need an associated 
completion status. 


Note that it is not considered an error if the requested action does not actually process any files, such as in 
a request to delete files from an empty directory. If such a condition needs to be reported, it may be 
detected by the receipt of an FMAN_COMPLETE message that is not preceded by one or more FMAN_NEWNAME 
messages. 


Typically, a subclass would use the receipt of this message to destroy any objects associated with the 
display of status information for the current operation and to allow further file management actions be 
selected. 


This method is expected to return. Any code that may result in p_leave being called must be run under 
the protection of p_enter. 


16-9 


OLIB REFERENCE 


& FMAN_NEWNAME Processing a new file 


VOID fman_newname(FCOPY_DISP *pinfo); 
Notify that processing is about to commence on a new file. 


Information about the file is contained in the rcopy_pisp struct pointed to by pinfo. This struct is 
declared in the rcasy class, since it contains data that is used by a number of rcasy subclasses. For 
convenience it is reproduced here: 


typedef struct 
{ 


UWORD flags; Which fields are valid 

UWORD protocol; Which protocol being used 

UWORD blksiz; Size of each block 

UWORD blkno; Current block number 

UWORD sftype; Source file type 

UWORD rftype; Receive file type 

ULONG sfsize; Source file size 

ULONG rfsize; Receive file size 

ULONG sfdate; Source file last modification date 
ULONG rfdate; Receive file last modification date 
UBYTE *sfname; Source file name 

UBYTE *rfname; Receive file name 


} FCOPY_DISP; 


Since, in general, not all fields contain valid information, the f1ags field indicates which of the fields are 
valid as follows: 


FCOPY_DISP_SFTYPE sftype contains either p_FTEXT Or P_FSTREAM 

FCOPY_DISP_SFSIZE sfsize contains the source file size, in bytes 

FCOPY_DISP_SFDATE sfdate contains, as a system time, the last modification date of the source file 

FCOPY_DISP_SFNAME sfname contains a pointer to the source file name as a zero terminated string 

FCOPY_DISP_RFTYPE rftype contains either p_FTEXT Or P_FSTREAM 

FCOPY_DISP_RFSIZE rfsize contains the remote or target file size in bytes 

FCOPY_DISP_RFDATE rfdate contains, as a system time, the last modification date of the remote or 
target file 

FCOPY_DISP_RFNAME rfname contains a pointer to the remote or target file name as a zero terminated 
string 

FCOPY_DISP_BLKSIZ blksiz contains a value that represents the amount of data that has been 
processed when each rMaN_UPDATE message is received 

FCOPY_DISP_BLKNO blkno contains a value specifying the current block number that is being 


processed (provided the appropriate fields are valid, the value of sfsize/blksiz 
equals the maximum value of b1kno that will be reached during the processing) 


FCOPY_DISP_PROTOCOL protocol contains a value specifying the current rman action (one of 
FMAN_COPYING, FMAN_DELETE, FMAN_RENAME, FMAN_MAKE, FMAN_REMOVE, 
FMAN_FORMAT, FMAN_NAME Of FMAN_ATTRIB) 


Irrespective of the contents of the flags field, the contents should not be read outside the fman_newname 
method. 


An FMAN_NEWNAME message is sometimes sent even if an error has prevented one or more fields from being 
set up. It is therefore essential always to check if a field is valid before using its contents. 


This method has two principal uses: 
e it provides information about the current stage of processing that may be presented to the user 


e it supplies a context for any particular error (for example, if a file is read only, it is known in 
advance that the p_delete service will fail with an E_rFILE_RDONLY error). 


This method is expected to return. Any code that may result in p_1leave being called must be run under 
the protection of p_enter. 


16 - 10 


16 FILE MANAGEMENT CLASSES 


& FMAN_UPDATE Section of processing completed 
VOID fman_update (VOID) ; 
Notify that the next section of the requested action has completed. 


The message will only be received during the processing of the copy and format services, each time that 
either a block of rmaN_READ_S1zE bytes has been copied, or that a section of the pack has been formatted. 


This method may be used to update any progress report that is being presented to the user. The values of 
fman.dispinfo.sfsize and fman.dispinfo.blksiz can be used to determine the number of times that an 
FMAN_UPDATE message will be received, in order to report a percentage completion to the user. Note that 
when formatting (that is, when fman.dispinfo.protocol has the value rmMan_rormat) only the low 16 bits 
of fman.dispinfo.sfsize contain valid data, so in this case the top 16 bits should be masked off. 


This method is expected to return. Any code that may result in p_leave being called must be run under 
the protection of p_enter. 


& FMAN_FILEEXIST File exists 


INT fman_fileexist (VOID); 
Notify that the destination file of a copy exists. 


This message will only be received only if fman.mode is not set to cause existing files to be replaced. It can 
therefore only be received if files are being copied as a result of an rMaN_copy message (and not 
FMAN_COPYDEV) Since the fman_copydev method sets fman.mode to include the p_rREPLAcE flag. 


The method is expected to return one of the following values: 
-1 (or any other negative value) abandon the copy service 
0 replace this file only, further clashing names will cause this message to be received again 
1 __ skip this file and continues with the next file 
2 replace this file and all subsequent files, regardless of whether the destination file exists. 


This method is expected to return. Any code that may result in p_1eave being called must be run under 
the protection of p_enter. 


& FMAN_ERROR Determine error response 
INT fman_error(INT errnum) ; 
Determine the action to be taken in response to a detected error with error number errnum. 


The method should return a value which specifies the form of error recovery. The range of options is 
different, depending on whether or not the current operation is a file copy (gman. action is 
FMAN_COPYING). 


During a file copy the return value may be one of: 
0 abandon copying the current file and continue with the following file 
1 (or any non-zero value) abandon the entire copy operation. 
During any other operation the return value may be one of: 
0 retry the operation on the current file 
1 abandon the entire operation 
2 abandon the operation on the current file and continue with the following file. 


This method is expected to return. Any code that may result in p_1leave being called must be run under 
the protection of p_enter. 


16-11 


OLIB REFERENCE 


FMMK 


ACTIVE FACTIVE FMMK 


gq owner 


priority 


isactive 
pcb 
stat 


destroy fa_close ao_run 
ao_init 
ao_cancel 
ao_abrun 

ao_queue 

See 


The rmx class is designed to be used as a component of rman which uses it to implement the make 
directory service. 


Since the supplied ao_run method contains assumptions about the property of the object whose handle is 
stored in factive.owner, it is not suitable for use other than as a component of rman. 


Class definition 
Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS fmmk factive 

The 'Create directory' active object 
{ 
REPLACE ao_run 


} 
Property 


None. 


FMMK methods 


AO_RUN Process a make directory request 
INT ao_run(VOID) ; 

Make the directory that was specified by an earlier rmMaN_MAKE message. 

Sends the owning FMAN an FMAN_NEWNAME Message, passing the address of rman's fman.dispinfo struct. 


Then makes the directory (and any necessary intermediate directories) with a call to p_mkdir. If this call 
returns an error, FMAN is sent an FMAN_ERROR message and, if this message returns FaLsz, a further attempt 
is made to create the directory. This is repeated until either the directory creation succeeds or the 
FMAN_ERROR message returns a non-zero value. 


Following this, rman is sent an FMAN_COMPLETE message to indicate that the processing is complete. Note 
that the ac_run method is executed only once for each rman_MaAKE message. 


The method returns RUN_ACTIVE_USED. 


16 - 12 


16 FILE MANAGEMENT CLASSES 


FMFMT 


ACTIVE FACTIVE 
q 


owner rdword 
priority rdlen 
isactive flags 
pcb 
stat 


destroy fa_close ao_run 
aorinit ao_init ao_abrun 
aereanecet | ao_cancel 


ao_queue 
aeTFuAn 


The rurnr class is designed to be used as a component of rman, which uses it to implement the format 
service. 


Since the supplied methods contain assumptions that the object whose handle is stored in fact ive.owner 
is an instance of the rman class, it is not suitable for use in other situations. 


Class definition 
Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS fmfmt factive 
Format active object 
{ 
REPLACE ao_run 
REPLACE ao_abrun 
CONSTANTS 
{ 
FMFMT_NAME 0x01 
} 
PROPERTY 
{ 
UWORD rdword; 
UWORD rdlen; 


UWORD flags; Controlling flags 
} 
} 
Property 
fmfmt .rdword a scratch buffer to receive data read during the format process. 
fmfmt .rdlen the number (two!) of bytes read into tmfmt .rdword 
fmfmt .flags controlling flag, initially set to rmmx_Nname and cleared on the first pass 


through the ao_run method 


FMFMT methods 


AO_RUN Process a format request 


INT ao_run(VOID); 
Perform a segment of the processing of a file manager format request. 


If this is the first time that the method has been called following a rman_rormat message, the first read is 
made, to obtain the format count, and the result is written to the bottom 16 bits of rman's 
fman.dispinfo.sfsize. Following this, rman is sent an FMAN_NEWNAME message, passing the address of 
FMAN'S fman.dispinfo struct. 


16 - 13 


OLIB REFERENCE 


On subsequent calls, unless an error condition is encountered, rman is sent an FMAN_UPDATE Message, 
active.stat is set to TRUE and another read is queued. 


If a read request completed with an &_FILE_koF error, indicating that the format is complete, the method 
sends itself an ra_cLOsE message and then sends rMaN an FMAN_COMPLETE Message. 


All other errors result in p_1eave being called. 


The method returns RUN_ACTIVE_USED. 


AO_ABRUN Process formatting error 
VOID ao_abrun (VOID) ; 
Process an error which caused the ao_run method to call p_ieave. 


Supersends an AO_ABRUN message and then sends rman an FMAN_COMPLETE message. 


FMSCAN 


ACTIVE FACTIVE FSCAN FMSCAN 
q 


owner 
priority 

isactive 

pcb 

stat 


destroy fa—etese fs_matchname ao_abrun 


ao_init fs_fscan fs_filename 


ao_cancel ao_queue fs_dirname 


aorebeun ao_run fs_end_dirlist 


fa_close fs_fscan_end 


The rmscan class is designed to be used as a component of rman, which uses it to implement the copy file, 
delete file, rename file, remove directory and copy device services. 


Since the supplied methods contain assumptions that the object whose handle is stored in fact ive.owner 
is an instance of the rman class, it is not suitable for use in other situations. 


Class definition 
Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS fmscan fscan 

File system scan active object 
{ 
REPLACE ao_abrun 
REPLACE fs_filename 
REPLACE fs_dirname 
REPLACE fs_end_dirlist 
REPLACE fs_fscan_end 
} 


Property 


None. 


16 - 14 


16 FILE MANAGEMENT CLASSES 


FMSCAN methods 


AO_ABRUN Process an error 


VOID ao_abrun (VOID); 
Handle any error that arises within the ao_run method (provided by rscan). 


Reads the owning rman's property and, if man. action iS FMAN_COPYING, sends Ao_CANCEL messages to the 
fman.srcfile and fman.targfile component objects. 


Then supersends the ao_aprun message and sends rMaAN an FMAN_COMPLETE message. 


FS_ FILENAME Next file name 


VOID fs_filename (VOID) ; 


Process a new file name during a file name scan (the full file specification of the file is in the fscan.name 
buffer). This method will be called during a copy file, copy device, delete file, delete directory, rename file 
or set attribute service. 


Reads the owning rmwan's property and performs one of the following actions, depending on the value of 


fman.action: 


FMAN_COPYING the name for the copy file is generated by merging the current file name 
from the scan with the wildcarded target name (from fman.wildtargname). 
If this is successful, the source and target files are opened by sending 
FC_OPEN messages to Fan's FMsRc and rmTarG components. The source file 
is opened in read only mode (with the p_rsuare flag set) and the target file 
in text (P_FSTREAM_TEXT) or binary mode, according to the source file type 
specified by fman.mode. 


Regardless of the success or failure of the name generation or the attempt to 
open the files, rman is sent an FMAN_NEWNAME message, passing the address of 
the fman.dispinfo struct (whose sfname and rfname elements point 
respectively to the source and target file names). This allows the user 
interface to display names that cause an error in addition to displaying valid 
names. 


The copy is started by sending an ao_QuEUE message to FMAN'S FMSRC 
component. Further processing is controlled by the rmsrc and rMTaRG 
components. 


FMAN_RENAME the file's new name is generated by merging the current file name from the 
scan and the wildcarded target name (from fman.wildtargname) and FMAN is 
sent an FMAN_NEWNAME message, passing the address of the fman.dispinfo 
struct (whose sfname and rfname elements point respectively to the old and 
new file names). Provided the name generation did not fail, the file is 
renamed. 


FMAN_ATTRIB sends FMAN an FMAN_NEWNAME message and sets the file's attributes according 
to the value of fman.mode. 


FMAN_DELETE or sends FMAN an FMAN_NEWNAME message and deletes the file. 
FMAN_REMOVE 


An £_FILE_EXxIsT error that occurs when trying to create the target file for a copy causes rman to be sent 
an FMAN_FILEEXIST message. See the earlier description of this method for the range of possible return 
values and the resulting actions. 


All other errors cause an FMAN_ERROR message to be sent to rman and the return value determines what 
form of error recovery action is taken. The range of possible actions depends on the service that is being 
processed. The various options are listed in the description of the fman_error method. 


Except when either copying files or, following an error, the user selects to abandon the entire operation, 
the scan is continued by sending rscan an Ao_QUEUE. 


16 - 15 


OLIB REFERENCE 


FS _DIRNAME Next directory name 


VOID fs_dirname (VOID) ; 


Process a new directory file during a file name scan. This method will be called when scanning into a 
subdirectory during a copy or delete service. 


Reads the owning Fan's property and, if fman. action 1S FMAN_COPYING, adjusts the contents of the 
fman.wildtargname buffer to refer to the new subdirectory. Any error here results in p_leave being 
called. 


Sends itself an Aao_QUEUE message to continue the scan. 


FS _END_DIRLIST End of subdirectory 


VOID fs_end_dirlist (VOID); 
Process the reaching of the end of a subdirectory during a file name scan. 


Reads the owning rvan's property and, if fman.action 18 FMAN_REMOVE, deletes the subdirectory whose 
name is specified in the fman.name buffer (any files contained in the subdirectory have been deleted earlier 
in the scan). Any error causes rman to be sent an FMAN_ERROR message. The return value determines the 
action as follows: 


0 retry the deletion until it succeeds, or the user decides to skip or abandon 


1 abandon the entire operation - send rmscan an AO_CANCEL message and FMAN an FMAN_COMPLETE 
message 


2 continue, without deleting the subdirectory. 


Otherwise, if man. action 1S FMAN_COPYING, adjusts the contents of the fman.wildtargname buffer to refer 
to the parent directory. Any error here results in p_leave being called. 


Sends itself an ao_quEUE message to continue the scan except following a user decision to abort. 


FS FSCAN_END Scan completion 


VOID fs_fscan_end(VOID); 
Process the end of the file name scan. 


Reads the owning rman's property and, if man. action is FMAN_REMOVE, deletes the directory whose name 
is specified in the fman.name buffer (any files and subdirectories have been deleted during the scan). If 
fman.name specifies the root directory, the attempt to delete it will, of course, fail but this is not considered 
an error. Any other error causes rman to be sent an FMAN_ERROR message. The return value determines the 
action as follows: 


0 retry the deletion until it succeeds, or the user decides to skip or abandon 


1 abort the entire operation - send rMscan an AO_CANCEL message and send rMaN an FMAN_COMPLETE 
message 


2 continue, without deleting the directory. 


Sends rvan an FMAN_COMPLETE message. 


16 - 16 


16 FILE MANAGEMENT CLASSES 


FMSRC 


ACTIVE FACTIVE FCASY 
q 


owner recvname 
priority flags 
isactive 

pcb 

stat 


destroy #a—ctese ao_cancel fc_request_comp 


ao_init ao_run 


2 + ao_queue 
ao_abrun fa_close 
fc_write 


fc_open 


The rsrc class is designed to be used as a component of rman which uses it to implement the reading of 
the source file in the copy file service. 


Since the supplied method contains assumptions that the object whose handle is stored in fact ive.owner 
is an instance of the rman class, it is not suitable for use in other situations. 


Class definition 
Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS fmsrc fcasy 
Source file active object 


{ 
REPLACE fc_request_comp 


} 
Property 


None. 


FMSRC methods 


FC_REQUEST COMP Process a read completion 


VOID fc_request_comp (VOID) ; 
Process the completion of a read from the source file. 


The read will always have been of rman_READ_S1zE bytes into rman's fman.buf buffer. On completion of 
the read fman.srcien contains the number of bytes actually read. 


If the read completed successfully, it sends an rc_wRITE message to FMAN's FMTARG component to write 
fman.srclen bytes from fman.buf to the destination file. 


If the read completed with an z_F1Lz_k£oF error, the copy of the file is complete. rman's FMTARG component 
is sent an FA_CLOSE message, the destination file is set to have the attributes and modification date of the 
source file (an error in reading the attributes of the source file causes p_leave to be called). If the copy is 
of modified files only, the modified (p_ramop) attribute of the source file is cleared. An ao_QUEUE message 
is sent to FMAN's FSCAN component to continue the scan for another file to copy. 


If the read completed with any other error, rman's FMTARG Component is sent an Ao_CANCEL message and 
FMAN is Sent an FMAN_ERROR Message, which allows the user to skip this file and continue, or abort the copy 
service. 


16-17 


OLIB REFERENCE 


FMTARG 


ACTIVE FACTIVE FCASY FMTARG 
q 


owner recvname 
priority flags 
isactive 

pcb 

stat 


destroy #a—ctese ao_cancel fc_request_comp 


ao_init ao_run 


ae-ean ao_queue 
ao_abrun fa_close 
fc_write 


fc_open 


The rmtare class is designed to be used as a component of rman, which uses it to implement the writing of 
the target file in the copy file service. 


Since the supplied method contains assumptions that the object whose handle is stored in fact ive.owner 
is an instance of the rman class, it is not suitable for use in other situations. 


Class definition 
Defined in sub-category file factive.cl (generated header file factive.g). 


CLASS fmtarg fcasy 
Target file active object 

{ 

REPLACE fc_request_comp 


} 
Property 


None. 


FMTARG methods 


FC_REQUEST COMP Process a write completion 


VOID fc_request_comp (VOID); 
Process the completion of a write to the target file. 


If the write completed successfully, sends rman an FMAN_UPDATE message, updates the value of rman's 
fman.srclen tO FMAN_READ_SIZE and sends an Ao_QUEUE message to FMAN'S FMSRC Component. 


If the write completed with an error, rmMan's FMSRC Component is sent an AO_CANCEL message and FMaN is 
sent an FMAN_ERROR message, which allows the user to skip this file and continue or abandon the copy 
service. 


16 - 18 


16 FILE MANAGEMENT CLASSES 


File manager example 


The following example is of a simple application to back up the contents of M-:, using a console window as 
the user interface. It formats an SSD in B: and copies the entire contents of M: to B:. The process may be 


aborted at any time by pressing the ESC key. 


The category file, mcopy.cat, is as follows: 


IMAGE mcopy 
EXTERNAL olib 


INCLUDE appman.g 
INCLUDE factive.g 
INCLUDE p_keyb.h 


CLASS bakfman fman 


File manager to perform format and copydev operations 


{ 
REPLACE fman_complete 
REPLACE fman_newname 
REPLACE fman_update 
REPLACE fman_error 
PROPERTY 
{ 
UWORD count; 
UWORD increment; 
UWORD maxcount; 
} 
} 


CLASS breakkey active 
Looks for Esc key being pressed 
{ 
REPLACE ao_init 
REPLACE ao_run 
REPLACE ao_queue 
PROPERTY 
{ 
P_CON_KBREC k; 
} 


CLASS bakapp appman 

{ 

REPLACE am_init 

PROPERTY 2 
{ 
PR_BAKFMAN *fman; 
PR_BREAKKEY *breakkey; 
} 

} 


Operation now complete 

Operation now on this file(s) 

Update copying display 

Error in operation, abandon/continue 


Note that no method function is supplied for the file manager's deferred fman_fileexist method. It will 
never be called in this example since the only file copies are ones that will replace any existing file of the 


Same name. 


16 - 19 


OLIB REFERENCE 


The code for the application is as follows. Note that pressing Esc during the format will leave the SSD in 
B: unformatted. 


#include <p_std.h> 
#include <p_gen.h> 
#include <p_file.h> 
#include <p_sys.h> 
#include <p_keyb.h> 
#include <epoc.h> 

#include <mcopy.g> 


GLREF_D PR_BAKAPP *w_am; 
GLREF_D VOID *winHandle; /* console device handle */ 


LOCAL_D INT escaped; 
#pragma save,METHOD_CALL 


METHOD VOID breakkey_ao_init (PR_BREAKKEY *self) 
{ 
self—>active.priority=PRIORITY_ACTIVE_WSERV; 
self->active.pcb=winHandle; /* console device must already be open */ 
p_send3 (w_am, O_AM_ADD_TASK, self) ; 
p_send2 (self, O_AO_QUEUE) ; 
} 


METHOD VOID breakkey_ao_queue (PR_BREAKKEY *self) 

/* 

Checks for ESC during file manager commands 

*/ 
{ 
p_ioc4 (self-—>active.pcb, P_FREAD, &self->active.stat, &self-—>breakkey.k) ; 
self—>active.isactive=TRUE; 


} 


METHOD breakkey_ao_run(PR_BREAKKEY *self) 


/* 
Aborts if ESC pressed 
baw A 
{ 
if (self->breakkey.k.keycode!=0x1b) 
p_send2 (self, O_AO_QUEUE) ; 
else 
{ 
escaped=TRUE; 
p_printf("\r\nUser aborted") ; 
p_send2 (w_am->bakapp.fman,O_FMAN_CANCEL); /* stops any service cleanly at any 
time */ 


} 
return (RUN_ACTIVE_USED) ; 
} 


METHOD bakfman_fman_error(PR_BAKFMAN *self,INT error) 
/* 
An error was detected in the operation of the engine. 
This method causes the operation to be abandoned and, 
in this example, results in the application being 
terminated. 
*/ 

{ 

escaped=TRUE; 

return (1); 


} 


16 - 20 


16 FILE MANAGEMENT CLASSES 


METHOD VOID bakfman_fman_complete (PR_BAKFMAN *self) 
/* 
The last requested operation is now complete, for ANY reason. 
xf 
{ 
if ((self->fman.action==FMAN_FORMAT) && (!escaped) ) 
p_printf("\r\n*** Format successfully completed ***\r\n"); 
p_send2 (w_am,O_AM_STOP) ; 
} 


#define FORMAT_FLAGS (FCOPY_DISP_BLKS1IZ|FCOPY_DISP_SFSIZE|FCOPY_DISP_SFNAME) 


METHOD VOID bakfman_fman_newname (PR_BAKFMAN *self,FCOPY_DISP *pinfo) 
/* 
A new file is being acted on by the engine. 
*/ 
{ 
if (self->fman.action==FMAN_COPYING) 
{ 
if (pinfo->flags&FCOPY_DISP_SFNAME) 
p_printf ("Copying %s",pinfo->sfname) ; 
} 
if (self->fman.action==FMAN_FORMAT) 
{ 
/* store some info to avoid accessing it outside this method */ 
self-—>bakfman.count=self->bakfman.maxcount=0; 
if ((pinfo->flags&FORMAT_FLAGS) ==FORMAT_FLAGS) 
{ 
self—>bakfman.increment=pinfo->blksiz; 
self—>bakfman.maxcount=pinfo->sfsize; 


/* copy sfsize into UWORD since, for format, only lower 16 bits are valid */ 


p_printf ("Formatting %s",pinfo->sfname) ; 


} 


METHOD VOID bakfman_fman_update (PR_BAKFMAN *self) 
/* 
Update display, as next copy/format block has been processed. 
Does not report progress on the copying of files. 
af 
{ 
if (self->fman.action==FMAN_FORMAT && self->bakfman.maxcount) 
{ 
self->bakfman.count+=self->bakfman.increment; 
p_print ("\r%05u %05u", self—>bakfman. count, self->bakfman.maxcount) ; 
} 
} 


METHOD bakapp_am_init (PR_BAKAPP *self) 
{ 


p_supersend3 (self,O_AM_INIT,FLG_APPMAN_CLEAN|FLG_APPMAN_ONLYONE) ; 
self—>bakapp.fman=f_newsend (CAT_MCOPY_MCOPY, C_BAKFMAN, O_FMAN_INIT) ; 
self—>bakapp.breakkey=f_newsend (CAT_MCOPY_MCOPY, C_BREAKKEY, O_AO_INIT) ; 
return (0); 


} 


16 - 21 


OLIB REFERENCE 


#pragma ENTER_CALL 


LOCAL_C INT RunIt (VOID) 
/* 
Runs the format and copy services. 
Designed to run in an enter harness. 
xf, 
{ 
f_leave (p_entersend5 (w_am—->bakapp.fman,O_FMAN_FORMAT, "LOC::B:\\", "BACKUP", 0) ); 
p_send2 (w_am,O_AM_START) ; 
if (!escaped) 
{ 
f_leave (p_entersend5 (w_am—>bakapp. fman, O_FMAN_COPYDEV, "LOC: :M:","LOC::B:",0)); 
p_send2 (w_am,O_AM_START) ; 
} 
p_send2 (w_am, O_DESTROY) ; 
return (FALSE) ; 
} 


LOCAL_C INT DoIt (VOID) 
/* 
Creates and initialises the application manager. 
Runs the format and copy services under a further enter harness. 
Designed to run in an enter harness to catch initialisation failures. 
*/ 

{ 

INT err; 


escaped=FALSE; 

w_am=(PR_BAKAPP *) f_new(CAT_MCOPY_MCOPY,C_BAKAPP) ; 
p_send2 (w_am,O_AM_INIT); 

err=p_enterl (RunIt); 

p_send2 (w_am, O_DESTROY) ; 

return(err); 


} 


#pragma restore 


GLDEF_C main(VOID) 


/* 
Copy all of M: to an SSD in B: 
tf 

{ 

p_linklib(0); 

p_printf ("Backing up M: to B:"); /* convenient way to start up the console device 
*/ 


return (p_enterl (DoIt)); 
} 


The nested p_enter protection for the calls to port and Runit ensure that the application manager is not 
sent a DEsTRoy message if it fails to be created, but is destroyed in the event of any other failure. 


The pEstRoy message is not strictly necessary since the operating system will clean up all resources used 
by an application when the application terminates. Nevertheless, it is good practice to ensure that an 
application is in a fit state to free its resources at any time. 


In this case, by use of the auto-destruction mechanism, destroying the application manager will cause the 
destruction of both the file manager and the preakkeEy active object. The superclass active object dest roy 
method ensures that any outstanding console keyboard read is cancelled and that the console device 
(whose handle is stored in active. pcb) is closed. 


16 - 22 


CHAPTER 17 


THE LOCS LOCAL FILE SCAN CLASS 


flags 


pcb 


pname 
match 
info 
name 


wildname 


1ls_matchname 


ls_scan 


ls_filename 


The tocs abstract class provides a set of methods to perform a synchronous scan of the LOC:: and ROM:: 
filing systems to locate file names which match a wildcarded name. It is similar in purpose to, but simpler 
than, the asynchronous scanning classes described in the File Active Objects and File Lists chapters. 


LOCS uses a synchronous scan, so once a scan has been started no other events can be processed until the 
scan completes. However, since file system requests on the LOC:: and ROM:: filing systems complete 
very quickly, this is unlikely to cause any significant loss of responsiveness to user input. 


Locs must be subclassed to provide the deferred Ls_FILENamME method, to process matching file names. 


Precursors 


The reader is assumed to understand: 
e the PLIB/EPOC file system directory read functions 
e =the LOC:: and ROM:: filing systems 


17-1 


OLIB REFERENCE 


Class definition 


The tocs class subclasses root and is defined in the sub-category file factive.cl (with generated header 
file factive.g). 


CLASS 


locs root 


Synchronous Local/ROM filing system file finder 


{ 


ADD 1ls_matchname 
ADD 1ls_scan 


DEFER 1s_filename 


CONSTANTS 


{ 
LOCS_FLG_ROM 
LOCS_FLG_LOC 


LOCS_FLG_ROOT 


Matching name checker 
Start the scan off 
Process located file name 


0x1000 
0x2000 
(0x4000 | LOCS_FLG_LOC) 


LOCS_FLG_ROOT_ONLY 0x4000 Internal to locs only 


} 


PROPERTY 


} 


{ 

UWORD flags; 
UBYTE *pcb; 
UBYTE *pname; 
UBYTE *match; 
P_INFO info; 


Controlling flags 

Open directory file handle 
Where to read names into 
Match name string 
Currently found file info 


UBYTE name [P_FNAMESIZE]; 
UBYTE wildname [P_FNAMESIZE]; 


} 


Property 


LOocs 


Locs 


Locs 


locs. 


locs 


locs 


17-2 


Ltocs. 


flags 


-pcb 


-pname 


-match 


info 


-name 


.-wildname 


controlling flags to drive the scan. This field should not be accessed by 
any subclass. 


the currently opened directory file handle. It should not be accessed by 
any subclass. 


a pointer to the name and extension within the full file specification in the 
locs.name buffer. A subclass may use this pointer to read the file name. 


a pointer to the name and extension within the wildcard full file 
specification in the locs.wildname buffer. Used to determine if a 
generated file name matches the name requirements. A subclass should 
treat this as read only. 


the file information corresponding to the file name in 1ocs.name, read 
from the currently opened directory file. A subclass should treat this as 
read only. 


the full file specification of the current file, whose file information is in 
locs.info. A subclass should treat this as read only. 


contains a parsed version of the wildcarded name passed to the 1s_scan 
method. If necessary, it is modified during the scan in order to search the 
ROM.:: and/or the root directories of the LOC:: filing systems. 


17 THE LOCS LOCAL FILE SCAN CLASS 


LOCS methods 
JLS SCAN Perform a file scan 


VOID 1ls_scan(UBYTE *pname, INT flags); 


Perform a synchronous search for files with names matching the wildcard string pointed to by pname and 
of type and location specified by flags. This method will not return until the scan is complete. 


The value of flags may be any ored combination of items from the following two groups: 


P_FAMOD select only modified files 

P_FAHIDDEN include hidden files 

P_FASYSTEM include system files 

LOCS_FLG_ROM scan the ROM-:: device (scanned first) 

LOCS_FLG_LOC scan the specified directory of all LOC:: devices (in alphabetical order) 

LOCS_FLG_ROOT scan the root directory of a LOC:: device before scanning any specified 
directory 


The method first copies the value of flags into locs. flags and parses the string pointed to by pname into 
the 1locs.wildname buffer. It then reads file names, from the directory files specified by pname and flags, 
into the 1ocs.name buffer. For each file name it sends an Ls_mMaTCHNAME message. If this returns TRUE it 
also sends an LS_FILENAME message. The sending of this message is under the protection of p_enter so 
that the 1s_scan method itself will never be terminated by a call to p_leave. 


The scan is terminated either when there are no more file names to read or when the 1s_ filename method 
returns a non-zero value. 


For example: 
p_send4 (locs, O_LS_SCAN, "fon\\*. fon", LOCS_FLG_ROM|LOCS_FLG_ROOT | LOCS_FLG_LOC) ; 


will find all fon files in the ROM, and in the root and \fon directories of all SSDs in the LOC:: filing 
system. 


J LS MATCHNAME Check file name match 


INT 1ls_matchname (VOID) ; 


Check the file name pointed to by 1ocs.pname, whose file type information is in locs. info, against the 
wildcarded name pointed to by 1ocs.match and the file types in locs. flags. 


This method is not called when the name is of a volume or a directory file. 


Returns true if the file matches the specified requirements else FaLsE. 


Deferred LOCS methods 
LS FILENAME Process a file name 


INT ls_filename(UBYTE *pname) ; 


This method should contain the logic to process the name of a file that matches the initial specifications as 
passed to the 1s_scan method. 


It is called from the 1s_scan method each time the 1s_matchname method returns TRUE, with pname 
pointing to the full file specification in the 1ocs.name buffer. If the subclass is only interested in the file 
name and extension, it may read this via locs.pname. 


The method is expected to return raLsE to continue the scan or, having found a file that satisfies its 
requirements, it may return TRUE to terminate the scan immediately, causing the 1s_scan method to 
return. 


If this method does not return TRUE the scan will terminate when the ts_scan method has no more file 
names to read. 


17 -3 


CHAPTER 18 


SYSTEM SERVICES 


Each member of the SIBO family of machines supplies one or more of the following global system 
services: 


e to allocate or replace an icon position, or to remove an icon 

e torun a file-based application by specifying the file that it is to open 
e¢ to nominate the current link paste server 

e to provide the process id of the current link paste server, if any 


All these services are available on MC 200/400 machines, where they are provided by the System process, 
SYSS$SHLL. 


On Series 3 and HC machines, only the two link paste related services are available and are supplied by 
the window server process, syss$wsRV. 


The available services are accessed by means of an inter-process message being sent to the supplying 
process. The system class provides a simplified form of access that hides the inter-process messaging 
mechanism. 


Precursors 


The reader is assumed to understand: 


e the initialisation of the appman class 


SYSTEM 


SYSTEM 


pid 


sy_init 


sy_icon_pos 


sy_link_server 
sy_link_paste 


sy_exec_open 


The system class provides simple access to the available system services, as described above. 


An application does not normally explicitly create and initialise an instance of the system class. On MC 
and Series 3 machines, an instance of the system class is usually created and initialised automatically by 
passing a flag (FLG_APPMAN_SYSTEM on the MC, or FLG_APPMAN_LINKING on the Series 3) to the application 
manager's aM_In1T method. In this case the handle of the created and initialised system instance is stored 
in the application manager's appman. system property field. 


Note that FLG_APPMAN_LINKING (which is defined in hwimman.g) and FLG_APPMAN_SYSTEM cause the 
appropriate process name (syS$SHLL or SYS$wsRvV respectively) to be used by the application manager's 
am_init method. 


18-1 


OLIB REFERENCE 


Class definition 


The system class subclasses root and is defined in the sub-category file appman.cl (with generated header 
file appman.g). 


CLASS system root 
For access to system services 


ADD sy_init Gets the pid of the supplying process 
ADD sy_icon_pos Allocate/remove/replace an icon position 
ADD sy_link_server Nominate oneself as the link paste server 
ADD sy_link_paste Get pid and format mask of link paste server 
ADD sy_exec_open Execute an application to open specified file 
CONSTANTS 
IC_SYSTEM_ALLOC 0) Allocate an icon position 
IC_SYSTEM_REMOVE 1 Remove an icon position 


IC_SYSTEM_REPLACE 2 Replace an icon position 
} 


PROPERTY 
UWORD pid; Process id of shell 
} 
} 
Property 
system.pid the process id of the System process. This is private to the SYSTEM class 


and should not be accessed by any other code 


SYSTEM methods 
J SY_INIT Initialise 


VOID sy_init (TEXT *sysnam) ; 


Initialise, by finding - and storing in system. pia - the process id of the System application whose 
application name is sysnam. 


Returns zero if successful. On error, writes nothing to system. pid and returns the relevant error number. 


As explained earlier, this method is not normally called explicitly by application code. It is called by the 
application manager in its am_init method which supplies the appropriate text. 


SY_ICON_POS Control icon positioning 


VOID sy_icon_pos(UINT req, P_POINT *pos, UINT prev); 
This service is only available on MC 200/400 machines. 
Control the positioning of icons representing tasks. The behaviour depends on the value of req, as follows: 


IC_SYSTEM_ALLOC Allocate an icon position, writing the allocated position in *pos and 
returning an index corresponding to this position. If prev is -1, the icon is 
allocated at the first free position. Otherwise prev should be an index 
returned by a previous sy_IcoN_Pos message, when an attempt will be made 
to allocate the corresponding position. If this position is occupied, the first 
free position is allocated, as for a prev of -1. 


IC_SYSTEM_REMOVE Remove the icon at position *pos, which should contain a position 
previously generated by an sy_sysTEM_Pos message with a req of either 
IC_SYSTEM_ALLOC Of IC_SYSTEM_REPLACE. The value of prev is ignored. 
Returns zero. 


IC_SYSTEM_REPLACE Replace the position corresponding to the index value in prev (which should 
be an index returned by a previous sy_1con_Pos message) with the position 
in *pos. The value in *pos is updated to be either the 'snap' position nearest 
to the passed position, or the original position if this nearest position is 
occupied. Returns an index corresponding to the new position. 


18 -2 


18 SYSTEM SERVICES 


SY_LINK_SERVER Set link paste server 


INT sy_link_server(ULONG fmask) ; 
Nominate the current process (that is, the process which sends this message) as the link paste server. 


The value of fmask is a bit mask of the formats in which the server is prepared to provide data. The 
formats are discussed in the description of the L1nxsv class definition in the Link Paste chapter of this 
manual. 


Returns zero. 


SY_LINK_PASTE Get link paste server 


INT sy_link_paste(ULONG *pfmt) ; 
Find the process id of the application (if any) that is the current link paste server. 


If such a process exists, writes the bit mask of available formats to *pfmt and returns the process id. The 
formats are discussed in the description of the L1nxsv class definition in the Link Paste chapter of this 
manual. 


If there is no current link paste server, writes nothing to *pfmt and returns zero. 


SY_EXEC OPEN Run an application by file name 
INT sy_exec_open(TEXT *pname) ; 
This service is only available on MC 200/400 machines. 


Queue a request to run the appropriate application that will open the file whose name is pointed to by 


pname. 


The application is selected on the basis of the file name extension together with the application/extension 
associations declared in one or more def.ext files. 


Returns zero without waiting for the request to complete. 


CHAPTER 19 


INTER-PROCESS COMMUNICATION 


This chapter describes the 1pcs and sERVER classes that may be used to receive and process inter-process 
messages from one or more sources. 


A process running under EPOC may open only one message channel for receiving inter-process messages. 
Inter-process messages may, however, arrive from a variety of sources. In order to distinguish between 
messages from different sources, it is conventional to group them, assigning a range of message type 
values to each source. (The type value is stored in the type field of the &_messacz struct that forms the 
header of each inter-process message.) 


The following message groups are defined and used by existing software: 


CONSOL message types 0 to OxOf (MC 200/400 only) 
TOPLIP message types 0x10 to Ox1f (MC 200/400 only) 
LINKSV message types 0x20 to Ox2f (link paste) 
Automatic test system message types 0x30 to Ox3f 


It is usually convenient to use a separate server object (by definition, a subclass of SERVER) to process the 
receipt of inter-process messages of each group. For example, all message types concerned with link paste 
should be handled by a link paste server object. 


The rpcs class provides the central mechanism by which a process receives an inter-process message and 
directs it to the appropriate server object. The relationship between 1pcs and server objects is analogous to 
that between appman and active objects. 


It may be noted that a process only needs to create an instance of the rpcs class (a message channel) if it 
receives messages; a process may send an inter-process message without opening a message channel. 


Precursors 
The reader is assumed to understand: 
e the active class and the application manager's event scheduling mechanisms 


e the PLIB inter-process messaging services, described in the Processes and Inter-process 
Messaging chapter of the PLIB Reference manual 


e =the p_enter and p_leave error handling services 


Inheritance tree 


— 


fs rec : — 
( active / 
sS ) 
U =. 
Pa es 
C Ilpcs  / 
“Ss ) 
‘ Pat 
cae 
( server / 
~~ {n} ) 
ee 


19-1 


OLIB REFERENCE 


IPCS 


ACTIVE 


gq 
priority 
isactive 
pcb 

stat 


destroy 
ao_init 
ao_cancel 
ao_queue 
ao_run 


ao_abrun 


ip_add_server 


The recs class is an active object that provides services to receive inter-process messages and dispatch 
them to the appropriate server object. 


This class should be used when several servers are required, to process messages of more than one group. 
It should also be used if the application is to support link paste. The application can then take advantage 
of the link paste server (described in the following chapter) even if no other servers are required. 


In other cases, where only one group of message types is to be processed, it may be more convenient to 
subclass recs so that the messages are processed in the subclass ao_run method, rather than in a separate 
server. 


An instance of the recs class is created and initialised automatically during the application manager's 
am_init method, provided the rLc_appman_1pcs flag is set, and its handle is written to appman.ipcs. 


If you subclass rpcs you must explicitly create and initialise the instance yourself. You must not specify 
the rLG_appman_ipcs flag in the am_In1IT message to aPpMaN (attempting to open more than one 
messaging channel will cause the application to fail). You may, however, store the handle in the 
application manager's appman.ipcs So that the object will be destroyed automatically when the application 
manager is destroyed at termination of the application. 


Class definition 
Defined in sub-category file appman.cl (generated header file appman.g). 


CLASS ipcs active 
The ipc server active object for inter-process communication 


{ 


REPLACE destroy Set pcb to NULL as not really handle based 
REPLACE ao_init Init message queue, add to appman queue, read 
REPLACE ao_cancel Cancel a queued message read 
REPLACE ao_queue Queue a message read 
REPLACE ao_run Despatch message to a server 
REPLACE ao_abrun Queue a read and supersend 
ADD ip_add_server Add a server to the queue 
PROPERTY 
{ 
P_QUE hd; Server queue header 
} 
} 
Property 
ipes.hd the head of the queue of server objects that can accept IPC messages. It 


should not be read or manipulated by any subclass. 


19-2 


19 INTER-PROCESS COMMUNICATION 


IPCS methods 
J DESTROY Destroy 


VOID destroy (VOID) ; 
Set active.pcb to NULL and supersend the pEstRoy message. 


Any non-zero value in active.pcb is a pointer to a message buffer for a received message; this is set in 
the ao_queue method. If active.pcb is non-zero, the superclass dest roy method assumes that it is an I/O 
channel and attempts to close it. Setting it to zero avoids the problem (and no information is "lost" by 
doing so). 


AO_INIT Initialise 


VOID ao_init (UINT size, UINT num); 
Initialise the IPCS object by performing a number of activities. 
e Initialise an empty server queue in ipcs.hd 


e Initialise a message queue of num messages; each message slot will consist of an E_MESSAGE 
header plus a buffer of length size. The queue is initialised using the PLIB function p_minit. 
Note that it is the receiver that specifies the size (and, by implication, the structure) of an inter- 
process message. 


e If the creation of the message queue is successful, the object adds itself, with priority 
PRIORITY_ACTIVE_1pcs, to the application manager's active object task queue and then sends 
itself an Ac_QUEUE Message. 


Calls p_leave on error. 


AO_QUEUE Queue a message read 
VOID ao_queue (VOID) ; 


If a message read is currently outstanding, indicated by active.isactive not set to FALSE, the method 
does nothing. 


If a message read is not outstanding, it queues a message read by calling p_mreceive, USINg active.stat 
as the completion status word. On completion of the read, the pointer to the received message slot will 
have been written to active.pcb. 


If the call to p_mreceive succeeds, active.isactive is set to TRUE. The call to p_mreceive will panic if 
messages have not been initialised or if an asynchronous message receive request is already pending. 


J AO CANCEL Cancel read request 


VOID ao_cancel (VOID); 


If a message read is not currently outstanding, indicated by active.isactive Set to FALSE, the method 
does nothing. 


If a message read is outstanding, it calls p_mcance1 to cancel any pending asynchronous request to receive 
a message and then waits (with p_waitstat ON active.stat) for the cancel to complete; it then sets 
active.isactive lO FALSE. 


AO_RUN Process a message 
INT ao_run(VOID); 
Pass the message to one of the servers in the server queue. 


Scans the items in the server queue until one is found that is prepared to process the type of message that 
has arrived (by comparing the message type with the upper and lower message type limits stored in each 
server's property). Calls p_panic (P_PANIC_P_IPcS_2) if no such server is found. 


19-3 


OLIB REFERENCE 


The first server that is prepared to process the message is sent an sv_RUN message under the protection of 
a p_enter (any error in the server's sv_run method is expected to result in a call to p_leave with a non 
zero error number). 


On detection of such an error the server is sent an sv_ABRUN message, after which the ao_run method 
itself calls p_leave to propagate the error (thus causing the receipt of an ac_ABRUN message). 


If there are no errors, the ac_run method sends an ao_QuEvE message to read another message and then 
returns RUN_ACTIVE_USED. 


AO_ABRUN Handle error 


VOID ao_abrun (VOID); 


Send an ao_QuEuE message to read another message before supersending the ao_aBRUN message. 


IP_ADD SERVER Add item to server queue 


VOID ip_add_server(PR_SERVER *hand) ; 


Add the server object pointed to by hand to the end of the server queue which is anchored in ipcs.had (i.e. 
in the 1pcs object). 


Unlike the application manager's queue, there is no priority system. If two servers can both handle a 
message of a particular type, the one that was first added to the server queue will be sent the sv_RuN 
message. 


Such a state is, in general, a programming error. Normally, each server is expected to handle a unique 
range of message types. Note that the message types handled by a server fall into a single range. 


SERVER 


SERVER 


destroy 
sv_abrun 


sv_init 


The server abstract class defines a set of services for processing a received inter-process message. 


SERVER must be subclassed to provide at least an sv_run method in order to create a useful server object. 
An example, the link paste server object, is described in the following chapter. 


Server objects work closely with an instance of the rpcs class (described above) whose handle is stored in 
the application manager's appman.ipcs. 


19-4 


19 INTER-PROCESS COMMUNICATION 


Class definition 
Defined in sub-category file ipc.cl (generated header file ipc.g). 


CLASS server root 
{ 


REPLACE destroy Dequeue and supersend 
ADD sv_abrun=p_dummy Handle leave from sv_run 
ADD sv_init Queue to ipcs 
DEFER sv_run Process message 
PROPERTY 
{ 
P_QUE q; Queue header 
UWORD t1; Server type range (lowest msg number) 
UWORD t2; (highest msg number) 
UWORD cid; Client process id, or zero for any process 
} 
} 
Property 
server.q used to add the server to an 1pcs server queue. It should not be accessed 
by any subclass. 
server.tl the lowest message type that is acceptable to this server. It is read by 1pcs 


and should not otherwise be accessed. 


server.t2 the highest message type that is acceptable to this server. It is read by 
recs and should not otherwise be accessed. 


server.cid intended for the storage of a client process id, if any. It is not used by 
either the sERvER or 1pcs Classes and is therefore free for use by any 
subclass. It may be used to store other information, if so required. 


SERVER methods 
J DESTROY Destroy 


VOID destroy (VOID); 


If the server object sits in an 1pcs server queue, i.e the queue anchored in ipcs.hd, remove it from the 
queue using p_deque. Then supersend a pEsTRoy message. 


SV_INIT Initialise 


VOID sv_init (UINT tl, UINT t2); 


Send an IP_ADD_SERVER message to the object whose handle is stored in the applications manager's (w_am) 
appman.ipcs property field. This object is assumed to be an instance of (a subclass of) the 1pcs class. 


Copies t1 and t2 to server.t1 and server.t2 respectively, to set the range of message types acceptable to 
this server. It is assumed that ¢2 is greater than (or equal) to ¢1. 


SV_ABRUN Handle error 
VOID sv_abrun (VOID); 
This method does nothing. It is called by recs, following a p_ieave in a server's sv_run method. 


A subclass may replace this method to perform specific error handling, over and above that subsequently 
executed in the 1Pcs ao_abrun method. 


This method is not expected to call p_leave. 


19-5 


OLIB REFERENCE 


Deferred SERVER methods 


SV_RUN Process a message 
VOID sv_run(E_MESSAGE *pmess) ; 
Process the message pointed to by pmess. 


This message is sent by 1pcs when it has determined that the message that has arrived is within the range 
of types that this server is prepared to process. 


19-6 


CHAPTER 20 


LINK PASTE 


Link paste is the term used for the transfer of data from one application to another, for example to transfer 
a database record into the document currently being edited in a word processor. Link paste is initiated by 
the Bring command in a Series 3 application and by a Link command in an MC 200/400 application. 


To clarify terminology, this chapter refers to a receiver and a supplier. A receiver is the process which 
asks for the data while the supplier is the process which provides that data. In the context of link-paste, a 
client is synonymous with a receiver while a server is synonymous with a supplier. 


The following description applies to applications written for the Series 3 or the MC 200/400. It does not 
apply to applications on the HC, since in this case the system class does not automatically provide access 
to the appropriate system services (see the System Services chapter of this manual) In general, custom 
applications written for the HC will need to provide their own means (usually by explicit inter-process 
messaging) for the receiver to identify a suitable supplier. Once this is done, however, the data may be 
transferred using instances of LInkcL and a subclass of L1nxsv, as described below. 


Link paste is implemented by means of inter-process messages sent by the receiver which are handled by 
the supplier of the data. The supplier uses a link paste server object which is generally an instance of a 
subclass of L1nxsv (link server). The receiver generally uses an instance of the L1nxcu (link client) class. 


A supplier of data is the passive partner in the transfer in the sense that it replies to IPCS messages sent 
by the receiver. A supplier does not send IPCS messages to the receiver. (See the description of 
p_msendreceivew in the PLIB Reference Manual) 


The supplying process must, however, register itself if it is capable of supplying data and must be able to 
specify in which set of data formats it is prepared to supply the data. A Series 3 or MC 200/400 
application may register itself as the current supplier by sending an sy_LINK_SERVER message to an owned 
instance of the system class. For example, if a word processor has a highlighted region of text when it is 
sent into background, it will, in general, register itself as the current supplier at that point. 


The range of possible formats are declared, for convenience, in the L1nxsv class definition. Their 
interpretation is significant to the application rather than to the LINKcL and Linxsv classes. 


A typical transaction is initiated by the receiver and requires the receiver to perform the following 
activities:- 


e It must first locate a process that is prepared to provide data in a suitable format. In the case of an 
application running on either the Series 3 or an MC machine, this is done by sending an 
SY_LINK_PASTE message to an owned instance of the system class to retrieve both the process id 
of the process which is currently registered as a supplier of data and a bit mask of the available 
data formats. 


e Jt must, at some stage, create an instance of the L1nxct class and send it an Lc_START message, 
passing the process id of the supplier and the particular format, from those available, in which 
the data is required. 


e It sends one or more Lc_GET_DATA messages (to the LINKCL object), passing both the address of a 
buffer which is ready to receive the data and the maximum length of data which can be handled. 
Once data has been received, it can be transferred into the application's own data structures. 


e =This should continue until either the available data is exhausted, in which case the transaction is 
automatically terminated, or until the receiver does not wish to receive further data. In this 
second case the receiver must send an Lc_sToP message (to the LINKCL object) to terminate the 
transaction. 


20-1 


OLIB REFERENCE 


The methods in the L1nxc1i and Linxsv classes and the particular values that their parameters take, in a 
sense, establish a protocol for communication between the receiver and supplier. 


Precursors 


The reader is assumed to understand: 
e inter-process messaging 
e the SERVER and recs classes 


Class diagram 


fe oe 
¢ server / 
= Aes. 
\ Patt | 
| aoe —~ 
i linkcl / 
) 
ee 
/ linksv / 
as ) 
aa 


LINKCL 


destroy 
lc_start 


lc_get_data 


lc_stop 


The t1nxcu class provides the methods by which a process may initiate a link paste data transfer, receive 
one or more sections of data and, if necessary, terminate the transaction. 


Class definition 
Defined in sub-category file ipc.cl (generated header file ipc.g). 


CLASS linkcl root 
The link client 
{ 


REPLACE destroy Stop the transaction then supersend 
ADD lc_start Start a transaction 
ADD lc_get_data Get a data record 
ADD lc_stop Stop the transaction 
PROPERTY 
{ 
UWORD pid; Process ID of link server 
} 
} 
Property 
linkcl.pid the process id of the process that is currently acting as the link paste 
server 


20 - 2 


20 LINK PASTE 


LINKCL methods 
J DESTROY Destroy 


VOID destroy (VOID); 


Stops any currently outstanding transaction with the link paste server by sending an Lc_sTop message 
before supersending the pEsTRoy message. 


LC_ START Initiate a transaction 


VOID lc_start (INT pid, INT format); 


Initiate a link paste transaction, requesting data of the type specified by format from the current link paste 
server process. 


pid is the process id of the current link paste server as retrieved by sending a sy_LINK_PASTE message to 
the receiver's owned system object. 


Records the link paste server's process id by setting 1inkcl.pid to pia and then sends a Ty_LINKSV_STEP 
inter-process message, containing the required data format, to the current link paste server process. 


Calls p_leave on error. 


LC GET DATA Request data 


UINT lc_get_data(UBYTE *buf, UINT len); 
Request up to 1en bytes of data to be written to the buffer pointed to by but. 


Sends a Ty_LINKSV_STEP inter-process message, containing the buffer pointer and maximum length, to the 
link paste server. 


If there is no more data to receive, 1inkcl.pid is set to zero, automatically terminating the transaction. A 
further Lc_sTART message is required in order to receive the data again. 


Returns one of: 
e the (positive) length of data written by the link paste server to the buffer, 
e «£ FILE_Eor if there is no more data to receive, 
e £_GEN_FaAIL if the transaction has not been initiated. 


Calls p_ieave on all other errors. 


LC STOP Terminate a transaction 
VOID lc_stop (VOID) ; 
Terminate any transaction with a link paste server. 


It effectively cancels any current transaction and then sets 1inkcl.pid to zero. It is harmless if there is no 
current transaction. 


An Lc_START message is required to start a further transaction. 


Calls p_leave on error. 


20 - 3 


OLIB REFERENCE 


LINKSV 


SERVER LINKSV 
q 


buf 
tl len 
t2 
cid 


destroy sv_init 


sv_abrun sv_run 
ae 
Sv is_set_format 


ls_get_data 


The t1nxsv abstract class provides the basic mechanisms for supplying, on request, sections of application 
data in one of a variable number of formats. 


LINKsv must be subclassed to supply the two deferred methods which depend on the way that the 
application interprets the data formats. The formats are discussed in the HWIM Reference manual. 


Class definition 
Defined in sub-category file ipc.cl (generated header file ipc.g). 


CLASS linksv server 
The link paste server 


{ 


REPLACE sv_init Supersend with parameters 
REPLACE sv_run Process message 

DEFER ls_set_format Set the desired format 
DEFER ls_get_data Get a data record 
CONSTANTS 


{ 
! Message types 


TY_LINKSV_STEP 0x21 Link paste step 
TY_LINKSV_DEATH Ox22 Death of client 
! Data formats - formats 0 to 31 inclusive are reserved for use by Psion 
DF_LINK_NATIVE 0 known only to another invocation of the 
supplying application 
DF_LINK_TEXT 1 plain ASCII text 
DF_LINK_TABTEXT 2 ASCII text including tab characters 
DF_LINK_VOICE 3 voice processor data 
DF_LINK_PARAS 4 text with a paragraph structure 
DF_LINK_SPR io) spreadsheet data 
DF_LINK_WRD 6 word processor data (only for Series 3a and later 
machines) 
DF_LINK_AGD q agenda data (only for Series 3a and later machines) 
} 
PROPERTY 
{ 
UBYTE *buf; Set by li_get_data 
UWORD len; Set by li_get_data 
} 
} 
Property 
linksv.buf a pointer to data, in the required format, available for copying to the 
client. This is read by the sv_run method and should be set by the 
deferred 1s_get_data method. 
linksv.len the length of the data pointed to by 1inksv.buf. This is read by the 


sv_run method and should be set by the deferred 1s_get_data method. 


20-4 


20 LINK PASTE 


LINKSV methods 


SV_INIT Initialise 


VOID sv_init (VOID) ; 


Supersend the sv_tn1tT message, specifying Ty_LINKSv_sTEP and Ty_LINKSvV_DEATH as the lower and 
upper inter-process message types that this server is prepared to handle. 


SV_RUN Process a message 


VOID sv_run(VOID); 
Process a received link paste inter-process message in the range Ty_LINKSV_STEP tO TY_LINKSV_DEATH. 


The handling of an inter-process message is fairly complex and depends on a number of factors, not least 
of which is the type of inter-process message received! 


Inter-Process Message ty_uinxsv_sTEP 


An inter-process message of type Ty_LINKsv_sTEP is part of a sequence of such messages transferring data 
from the client to the server. The method distinguishes between the first Tty_LINKSV_sTEP inter-process 
message and subsequent inter-process messages of this type. 


First ry_tinxsv_step inter-process message 


The first ty_LINKSV_STEP inter-process message represents a new transaction and corresponds to 
the client sending an Lc_sTarT message to an instance of its LtnKcL object. The link-server object 
decides that this is the first time if the property server.cid is zero. 


The following is done:- 
e The process ID of the client is saved in server.cid. 


@ p_logon is called to request that the syssmane process send it a TY_LINKSV_DEATH inter- 
process message if the client terminates. 


e The Ty_LINksv_sTEP inter-process message contains the required data format and this is 
passed as the parameter to an Ls_sET_FORMAT message which should register the format in 
which the data is to be provided. 


e The inter-process message is freed by calling p_mfree with a reply value of zero. 


Subsequent ry_tinxsv_step inter-process messages 


Subsequent Ty_LINKSvV_STEP inter-process messages are expected to contain a pointer to a buffer 
and a maximum length in the message data, as set by the LINKcL 1c_get_data method. Two 
situations must be handled - the buffer pointer is zero or non-zero. 


Zero buffer pointer 


A zero buffer pointer is taken to mean that the client wishes to terminate the link paste 
transaction. This is effectively a cancel and corresponds to the client sending an Lc_stTop 
message to an instance of its LInKcL object. 


The following is done:- 


e an LS_GET_DATA message is sent with a parameter of -1. The effect of this is to cause the 
deferred 1s_get_data method to tidy and reset the link server object in preparation for a new 
transaction. 


® p_logoff is called to cancel the request that the syssmanc process send a Ty_LINKSV_DEATH 
inter-process message on termination of the client. 


@ server.cid which contains the process id of the link paste client (i.e. the receiver), is set to 
zero, therefore losing all knowledge of that client 


e The inter-process message is freed (p_mfree) returning =_FILE_EoF to the client. 


20-5 


OLIB REFERENCE 


Non-zero buffer pointer 


A non-zero buffer is taken to mean that the client is making a request for (more) data. An 
LS_GET_DATA message is sent to retrieve an amount of data not exceeding the maximum length. 


If the 1s_get_data method returns a non-zero value:- 


e itis assumed that 1inksv.buf and linksv.1len have been set to indicate available data, 
which is copied to the client's buffer. 


e The inter-process message is freed (p_mfree) returning a value equal to the length of the data 
copied to the client's buffer. 


If the 1s_get_data method returns a zero value:- 
e this is taken to mean that no more data is available. 


@ p_logoff is called to cancel the request that the syssmanc process send a Ty_LINKSV_DEATH 
inter-process message on termination of the client. 


@ server.cia which contains the process id of the link paste client is set to zero, therefore 
losing all knowledge of that client 


e The inter-process message is freed (p_mfree) returning =E_FILE_EoF to the client. 


Inter-Process Message ry_utinxsv_pDEATH 


An inter-process message of type Ty_LINKSV_DEATH means that the link paste client died or was 
terminated during the inter-process data transfer. 


On receipt of this inter-process message, the following is done:- 
e The inter-process message is freed (p_mfree) 


e@ server.cid which contains the process id of the link paste client is set to zero, therefore losing 
all knowledge of that client 


e an LS_GET_DATA message is sent with a parameter of -1. The effect of this is to cause the deferred 
1s_get_data method to tidy and reset the link server object in preparation for a new transaction. 


Deferred LINKSV methods 
LS SET FORMAT Set data format 


VOID 1ls_set_format (UINT format) ; 


Register the data format in which data is to be provided. For link paste initiated by one of the built-in 
applications, the format will be one of the pr_L1nx_xxx values listed in the L1nxsv class definition. 


The method should call p_1eave on error. 


LS GET DATA Provide data 


INT ls_get_data(UINT len); 
Provide not more than 1en bytes of data in the currently specified format. 


A pointer to the data and its length should be written to Linksv.buf and 1inksv.1len respectively. The 
method should return zero if there is no more data available, else a positive number. 


A value of -1 for 1en indicates that the client process no longer requires data. In this case the method 
should tidy up and reset any variables so that future Ls_GzT_paTa messages read the data from the start of 
available data. 


The method should call p_1eave on error. 


20 - 6 


INDEX 


.trm files 
serial port parameters, 8-11 
ACTIVE class 
AO_ABRUN method, 11-4 
AO_CANCEL method, 11-3 
AO_INIT method, 11-3 
AO_QUEUE method, 11-3 
AO_RUN method, 11-4 
DESTROY method, 11-3 
methods, 11-3 
oop, 11-1 
active objects 
asynchronous I/O devices, 11-1 
class, 11-1 
file, 14-1 
file server and, 11-1 
priorities, 10-2 
return value, 10-3 
scheduling mechanism, 10-6 
scheduling, 10-3 
TIMER, 13-1 
AIDLE class 
AO_INIT method, 12-2 
AO_RUN method, 12-2 
compute intensive tasks, 12-1 
example, 12-3 
idle time computation, 12-3 
methods, 12-2 
oop, 12-1 
pause an operation, 12-3 
AIDLE example 
oop, 12-3 
AM_ADD_TASK 
APPMAN class method, 10-9 
AM_CHANGE_PRI 
APPMAN class method, 10-12 
AM_CLEAN_UP 
APPMAN class method, 10-11 
AM_FINDIMG 


AM_INIT 

APPMAN class method, 10-5 
AM_LOAD_RES_BUF 

APPMAN class method, 10-10 
AM_LOAD_RESOURCE 

APPMAN class method, 10-9 
AM_NOTIFY 

APPMAN class method, 10-10 
AM_NOTIFYERR 

APPMAN class method, 10-11 
AM_ONLYONE 

APPMAN class method, 10-12 


AM_RSCNAME 

APPMAN class method, 10-10 

AM_START 

APPMAN class method, 10-6 

AM_STOP 

APPMAN class method, 10-9 

AM_WAIT 

APPMAN class method, 10-6 

ANIMATOR class 
AO_INIT method, 13-4 
AO_RUN method, 13-4 
methods, 13-4 
oop, 13-3 

AO_ABRUN 
ACTIVE class method, 11-4 
FACTIVE class method, 14-3 
FMFMT class method, 16-14 
FMSCAN class method, 16-15 
IPCS class method, 19-4 
PNODE class method, 15-4 
PSEL class method, 15-7 

AO_CANCEL 
ACTIVE class method, 11-3 
BUZSND class method, 13-6 
FACTIVE class method, 14-2 
FCASY class method, 14-12 
IPCS class method, 19-3 
PSEL class method, 15-7 

AO_INIT 
ACTIVE class method, 11-3 
AIDLE class method, 12-2 
ANIMATOR class method, 13-4 
BUZSND class method, 13-5 
FACTIVE class method, 14-2 
IPCS class method, 19-3 
PSEL class method, 15-7 
TIMER class method, 13-2 

AO_QUEUE 
ACTIVE class method, 11-3 
BUZSND class method, 13-6 
FCASY class method, 14-12 
FCSYNC class method, 14-15 
FNODE class method, 14-9 
FSCAN class method, 14-5 
IPCS class method, 19-3 
TIMER class method, 13-2 

AO_RUN 
ACTIVE class method, 11-4 
AIDLE class method, 12-2 
ANIMATOR class method, 13-4 
BUZSND class method, 13-6 
FCASY class method, 14-13 
FMFMT class method, 16-13 
FMMK class method, 16-12 
FNODE class method, 14-9 
FSCAN class method, 14-5 
IPCS class method, 19-3 

APPMAN class 
AM_ADD_TASK method, 10-9 
AM_CHANGE__ PRI method, 10-12 
AM_CLEAN_UP method, 10-11 
AM_FINDIMG method, 10-11 


OLIB REFERENCE 


AM_INIT method, 10-5 cl_remove 
AM_LOAD_RES_BUF method, 10-10 CLEANUP class function, 9-6 
AM_LOAD_RESOURCE method, 10-9 CL_REMOVE 


AM_NOTIFY method, 10-10 
AM_NOTIFYERR method, 10-11 
AM_ONLYONE method, 10-12 
AM_RSCNAME method, 10-10 
AM_START method, 10-6 
AM_STOP method, 10-9 
AM_WAIT, 10-6 

definition, 10-4 

diagram, 10-4 

methods, 10-5 


CLEANUP class method, 9-3 
CL_SET_LEVEL 

CLEANUP class method, 9-4 
class 

ACTIVE, 11-1 

AIDLE, 12-1 

ANIMATOR, 13-3 


application manager definition, 10-4 
application manager diagram, 10-4 
application manager, 10-1 


oop, 10-1 application manager property, 10-5 
property, 10-5 BFILE, 8-2 
ARRAY VARIABLE binary files, 8-1 
classes, 5-1 BUZSND, 13-4 
asynchronous cleanup, 9-1 
I/O devices active object, 11-1 editable documents, 6-1 
BFILE class EPFLAT, 6-7 
DESTROY method, 8-3 EPROOT, 6-2 
FI_CLOSE method, 8-3 EPSEG, 6-10 
FI_OPEN method, 8-3 FACTIVE, 14-1 
FI_READ method, 8-3 FCASY, 14-11 
FL_REWIND method, 8-4 FCSYNC, 14-14 
FL_SENSE_DATA method, 8-4 FMAN, 16-2 
FL_SET_BUF_LEN method, 8-3 FMFMT, 16-13 
methods, 8-3 FMMK, 16-12 
oop class, 8-2 FMSCAN, 16-14 
BINARY FILE FMSRC, 16-17 
classes, 8-1 FMTARG, 16-18 
bring FNODE, 14-8 
IPCS, 20-5 FSCAN, 14-3 
oop, 20-1 idle object, 12-1 
BUZSND class IPCS, 19-2 
AO_CANCEL method, 13-6 LINKCL, 20-2 
AO_INIT method, 13-5 LINKSV, 20-4 
AO_QUEUE method, 13-6 PNODE, 15-3 
AO_RUN method, 13-6 PSEL, 15-4 
methods, 13-5 PSELVAR, 15-2 
oop, 13-4 resource files, 7-1 
cl_add ROOT, 2-1 
CLEANUP class function, 9-4 SCAN, 17-1 
CL_ADD SERFILE, 8-11 
CLEANUP class method, 9-3 SERVER, 19-4 
cl_add_alloc SGBUF, 4-1 
CLEANUP class function, 9-5 SYSTEM, 18-1 
cl_add_dyl TIME, 3-1 
CLEANUP class function, 9-5 TIMER, 13-1, 13-2 
cl_add_iochan TLVDATA, 8-8 
CLEANUP class function, 9-5 TLVFILE, 8-4 
cl_add_object VAFIX, 5-9 
CLEANUP class function, 9-4 VAFLAT, 5-14 
cl_add_shared variable array classes, 5-1 
CLEANUP class function, 9-5 VAROOT, 5-3 
cl_clean_item VASEG, 5-16 
CLEANUP class function, 9-6 VASTR, 5-11 
CL_CLEAN_ITEM VAXVAR, 5-18 
CLEANUP class method, 9-3 VAXVARS, 5-21 
CL_CLEAN_LEVEL class diagrams 
CLEANUP class method, 9-4 OLIB hierarchy, 1-3 
CL_INIT OLIB library, 1-3 
CLEANUP class method, 9-3 classes 


OLIB library overview, 1-1 


OLIB library using, 1-2 
CLEANUP class 
cl_add function, 9-4 
CL_ADD method, 9-3 
cl_add_alloc function, 9-5 
cl_add_dyl function, 9-5 
cl_add_iochan function, 9-5 
cl_add_object function, 9-4 
cl_add_shared function, 9-5 
cl_clean_item function, 9-6 


CL_CLEAN_ITEM method, 9-3 
CL_CLEAN_LEVEL method, 9-4 


CL_INIT method, 9-3 
cl_remove function, 9-6 
CL_REMOVE method, 9-3 


CL_SET_LEVEL method, 9-4 


DESTROY method, 9-3 
functions convenience, 9-4 
methods, 9-3 
oop, 9-1 
compute intensive tasks 
AIDLE class, 12-1 
DatCommandPtr 
magic static, 10-11 
DESTROY 
ACTIVE class method, 11-3 
BFILE class method, 8-3 
CLEANUP class method, 9-3 
EPFLAT class method, 6-8 
IPCS class method, 19-3 
LINKCL class method, 20-3 
ROOT class method, 2-2 
RSCFILE class method, 7-2 
SERVER class method, 19-5 
SGBUF class method, 4-2 
VAROOT class method, 5-4 
documents editable 
classes, 6-1 
DYL 


EP_COPY_TO_FRONT 

EPROOT class method, 6-5 
EP_DELETE 

EPFLAT class method, 6-9 

EPSEG class method, 6-11 
EP_EXTRACT 

EPFLAT class method, 6-9 

EPSEG class method, 6-11 
EP_INIT 

EPFLAT class method, 6-8 

EPSEG class method, 6-10 
EP_INSERT 

EPFLAT class method, 6-8 

EPSEG class method, 6-11 
EP_MOD_CHARS 

EPROOT class method, 6-6 
EP_PARA_COUNT 

EPROOT class method, 6-4 
EP_PASTE 

EPROOT class method, 6-6 
EP_SCAN_BLOCK 

EPROOT class method, 6-4 
EP_SCAN_PARA 

EPROOT class method, 6-4 
EP_SCAN_WORD 

EPROOT class method, 6-4 
EP_SENSE_CHARS 

EPFLAT class method, 6-8 

EPSEG class method, 6-11 
EP_SENSE_LEN 

EPFLAT class method, 6-8 

EPSEG class method, 6-11 
EP_SENSE_TEXT 

EPROOT class method, 6-6 
EP_SET_TEXT 

EPROOT class method, 6-3 
EP_WORD COUNT 

EPROOT class method, 6-4 
EPFLAT class 


OLIB library introduction, 1-1 


editable documents class 

oop, 6-1 
EF_GRANULARITY 

EPFLAT class method, 6-9 
EF_SENSE_BUF 

EPFLAT class method, 6-9 
EP_ADD_PARA 

EPROOT class method, 6-5 
EP_BACK_ CHARS 

EPFLAT class method, 6-8 

EPSEG class method, 6-11 
EP_CAPACITY 

EPFLAT class method, 6-9 

EPROOT class method, 6-6 
EP_CLEAR 

EPFLAT class method, 6-9 

EPSEG class method, 6-11 
EP_COMPRESS 

EPFLAT class method, 6-9 

EPSEG class method, 6-11 
EP_COPY_INDENT 

EPROOT class method, 6-5 
EP_COPY_TO_BACK 

EPROOT class method, 6-5 


DESTROY method, 6-8 


EF_GRANULARITY method, 6-9 


EF_SENSE_BUF method, 6-9 
EP_BACK_CHARS method, 6-8 
EP_CAPACITY method, 6-9 
EP_CLEAR method, 6-9 
EP_COMPRESS method, 6-9 
EP_DELETE method, 6-9 
EP_EXTRACT method, 6-9 
EP_INIT method, 6-8 
EP_INSERT method, 6-8 
EP_SENSE_CHARS method, 6-8 
EP_SENSE_LEN method, 6-8 
methods, 6-8 

oop class, 6-7 


EPROOT class 


EP_ADD_PARA method, 6-5 
EP_CAPACITY method, 6-6 
EP_COPY_INDENT method, 6-5 


EP_COPY_TO_BACK method, 6-5 
EP_COPY_TO_FRONT method, 6-5 


EP_MOD_CHARS method, 6-6 
EP_PARA_COUNT method, 6-4 
EP_PASTE method, 6-6 
EP_SCAN_BLOCK method, 6-4 


INDEX 


iii 


OLIB REFERENCE 


EP_SCAN_PARA method, 6-4 
EP_SCAN_WORD method, 6-4 
EP_SENSE_TEXT method, 6-6 
EP_SET_TEXT method, 6-3 


EP_WORD COUNT method, 6-4 


methods deferred, 6-6 

methods, 6-3 

oop class, 6-2 
EPSEG class 


EP_BACK_CHARS method, 6-11 


EP_CLEAR method, 6-11 
EP_COMPRESS method, 6-11 
EP_DELETE method, 6-11 
EP_EXTRACT method, 6-11 
EP_INIT method, 6-10 
EP_INSERT method, 6-11 


EP_SENSE_CHARS method, 6-11 


EP_SENSE_LEN method, 6-11 
methods, 6-10 
oop class, 6-10 
error handling 
OLIB library, 1-4 
OLIB library panics, 1-5 
FA_CLOSE 
FACTIVE class method, 14-3 
FCASY class method, 14-13 
FNODE class method, 14-10 
FSCAN class method, 14-6 
FACTIVE class 
AO_ABRUN method, 14-3 
AO_CANCEL method, 14-2 
AO_INIT method, 14-2 
FA_CLOSE method, 14-3 
methods, 14-2 
oop, 14-1 
FC_OPEN 
FCASY class method, 14-13 
FC_REQUEST_COMP 
deferred method, 14-14 


FCASY class method deferred, 14-14 


FMSRC class method, 16-17 
FMTARG class method, 16-18 
FC_WRITE 
FCASY class method, 14-12 
FCSYNC class method, 14-15 
FCASY class 
AO_CANCEL method, 14-12 
AO_QUEUE method, 14-12 
AO_RUN method, 14-13 
FA_CLOSE method, 14-13 
FC_OPEN method, 14-13 
FC_WRITE method, 14-12 
methods deferred, 14-14 
methods, 14-12 
oop, 14-11 
FCASY sub-class 
oop, 14-1 
FCSYNC class 
AO_QUEUE method, 14-15 
FC_WRITE method, 14-15 
methods, 14-15 
oop, 14-14 
FCSYNC sub-class 
oop, 14-1 


FI_CLOSE 

BFILE class method, 8-3 
FI_OPEN 

BFILE class method, 8-3 

TLVFILE class method, 8-6 
FI_READ 

BFILE class method, 8-3 
file 

active object, 14-1 
FILE BINARY 

classes, 8-1 
file I/O 

active objects and, 11-1 
file lists 

oop, 15-1 
file management 

oop, 16-1 
file manager 

example code, 16-19 
file scan local 

oop, 17-1 
file server 

active objects and, 11-1 
files 

type-length-value, 8-4 
filing system 

nodes, 14-8 
FL_COUNT 

TLVFILE class method, 8-6 
FL_DELREC 

TLVFILE class method, 8-7 
FL_READ_BY_TYPE 

TLVFILE class method, 8-7 
FL_REPLACE 

TLVFILE class method, 8-7 
FL_REWIND 

BFILE class method, 8-4 

TLVFILE class method, 8-6 
FL_SENSE_DATA 

BFILE class method, 8-4 
FL_SENSE_REC 

TLVFILE class method, 8-7 
FL_SET_BUF_LEN 

BFILE class method, 8-3 
FL_SET_REC 

TLVFILE class method, 8-6 
FL_WRITE_REC 

TLVFILE class method, 8-6 
FMAN class 

file management, 16-1 
FMAN_ATTRIB method, 16-8 
FMAN_CANCEL method, 16-4 


FMAN_COPY method, 16-5 
FMAN_COPYDEV method, 16-7 
FMAN_DELETE method, 16-5 


16-11 
FMAN_FORMAT method, 16-8 
FMAN_INFO method, 16-8 
FMAN_INIT method, 16-4 
FMAN_MAKE method, 16-7 
FMAN_NAME method, 16-8 


FMAN_COMPLETE deferred method, 16-9 


FMAN_ERROR deferred method, 16-11 
FMAN_FILEEXIST deferred method, 


FMAN_NEWNAME deferred method, 
16-10 
FMAN_REMOVE method, 16-7 
FMAN_RENAME method, 16-6 
FMAN_UPDATE deferred method, 16-11 
methods deferred, 16-9 
methods, 16-4 
oop, 16-2 
FMAN_ATTRIB 
FMAN class method, 16-8 
FMAN_CANCEL 
FMAN class method, 16-4 
FMAN_COMPLETE 
FMAN class method deferred, 16-9 
FMAN_COPY 
FMAN class method, 16-5 
FMAN_COPYDEV 
FMAN class method, 16-7 
FMAN_DELETE 
FMAN class method, 16-5 
FMAN_ERROR 
FMAN class method deferred, 16-11 
FMAN_FILEEXIST 
FMAN class method deferred, 16-11 
FMAN_FORMAT 
FMAN class method, 16-8 
FMAN_INFO 
FMAN class method, 16-8 
FMAN_INIT 
FMAN class method, 16-4 
FMAN_MAKE 
FMAN class method, 16-7 
FMAN_NAME 
FMAN class method, 16-8 
FMAN_NEWNAME 
FMAN class method deferred, 16-10 
FMAN_REMOVE 
FMAN class method, 16-7 
FMAN_RENAME 
FMAN class method, 16-6 
FMAN_UPDATE 
FMAN class method deferred, 16-11 
FMFMT class 
AO_ABRUN method, 16-14 
AO_RUN method, 16-13 
methods, 16-13 
oop, 16-13 
FMFMT sub-class 
oop, 16-1 
FMMK class 
AO_RUN method, 16-12 
methods, 16-12 
oop, 16-12 
FMMkK sub-class 
oop, 16-1 
FMSCAN class 
AO_ABRUN method, 16-15 
FS_DIRNAME method, 16-16 
FS_END_DIRLIST method, 16-16 
FS_FILENAME method, 16-15 
FS_FSCAN_END method, 16-16 
methods, 16-15 
oop, 16-14 


INDEX 


FMSCAN sub-class 
oop, 16-1 
FMSRC class 
FC_REQUEST_COMP method, 16-17 
methods, 16-17 
oop, 16-17 
FMSRC sub-class 
oop, 16-1 
FMTARG class 
FC_REQUEST_COMP method, 16-18 
methods, 16-18 
oop, 16-18 
FMTARG sub-class 
oop, 16-1 
FN_END_LIST 
FNODE class method deferred, 14-10 
PNODE class method, 15-4 
FN_LIST 
FNODE class method, 14-10 
FN_NODENAME 
FNODE class method deferred, 14-10 
PNODE class method, 15-4 
FNODE class 
AO_QUEUE method, 14-9 
AO_RUN method, 14-9 
FA_CLOSE method, 14-10 
FN_END_LIST deferred method, 14-10 
FN_LIST method, 14-10 
FN_NODENAME deferred method, 14-10 
methods deferred, 14-10 
methods, 14-9 
oop, 14-8 
FENODE sub-class 
oop, 14-1 
FS_DIRNAME 
FMSCAN class method, 16-16 
FSCAN class method deferred, 14-7 
PSEL class method, 15-8 
FS_END_DIRLIST 
FMSCAN class method, 16-16 
FSCAN class method deferred, 14-8 
FS_FILENAME 
FMSCAN class method, 16-15 
FSCAN class method deferred, 14-7 
PSEL class method, 15-8 
FS_FSCAN 
FSCAN class method, 14-6 
FS_FSCAN_END 
FMSCAN class method, 16-16 
FSCAN class method deferred, 14-7 
PSEL class method, 15-8 
FS_MATCHNAME 
FSCAN class method, 14-6 
FSCAN class 
AO_QUEUE method, 14-5 
AO_RUN method, 14-5 
FA_CLOSE method, 14-6 
FS_DIRNAME deferred method, 14-7 
FS_END_DIRLIST deferred method, 14-8 
FS_FILENAME deferred method, 14-7 
FS_FSCAN method, 14-6 
FS_FSCAN_END method, 14-7 
FS_MATCHNAME method, 14-6 
methods deferred, 14-7 


OLIB REFERENCE 


methods, 14-5 
oop, 14-3 
FSCAN sub-class 
oop, 14-1 
functions 
CLEANUP class convenience, 9-4 
HWIM 
active object, 11-1 
application manager class, 10-1 
idle object, 12-1 
I/O asynchronous 
active object, 11-1 
idle object 
class, 12-1 
IDLE OBJECT 
class, 12-1 
idle time 
AIDLE class computation, 12-3 
INTER-PROCESS COMMUNICATIONS 
class, 19-1 
IP_ADD_SERVER 
IPCS class method, 19-4 
IPCS 
bring, 20-5 
class, 19-1 
link paste, 20-5 
IPCS class 
AO_ABRUN method, 19-4 
AO_CANCEL method, 19-3 
AO_INIT method, 19-3 
AO_QUEUE method, 19-3 
AO_RUN method, 19-3 
DESTROY method, 19-3 
IP_ADD_SERVER method, 19-4 
methods, 19-3 
services, 19-2 
LC_GET_DATA 
LINKCL class method, 20-3 
LC_START 
LINKCL class method, 20-3 
LC_STOP 
LINKCL class method, 20-3 
library 
OLIB DYL introduction, 1-1 
link paste 
IPCS, 20-5 
LINK PASTE 
classes, 20-1 
LINKCL class 
DESTROY class method, 20-3 
LC_GET_DATA class method, 20-3 
LC_START class method, 20-3 
LC_STOP class method, 20-3 
methods, 20-3 
services, 20-2 
LINKSYV class 
LS_GET_DATA class method, 20-6 
LS_SET_FORMAT class method, 20-6 
methods deferred, 20-6 
methods, 20-5 
services, 20-4 
SV_INIT class method, 20-5 
SV_RUN class method, 20-5 


LOC 
filing system node, 14-8, 17-1 
LOCS class 
LS_FILENAME deferred method, 17-3 
LS_MATCHNAME method, 17-3 
LS_SCAN method, 17-3 
methods deferred, 17-3 
methods, 17-3 
LS_FILENAME 
LOCS class method deferred, 17-3 
LS_GET_DATA 
LINKSV class method deferred, 20-6 
LS_MATCHNAME 
LOCS class method, 17-3 
LS_SCAN 
LOCS class method, 17-3 
LS_SET_FORMAT 
LINKSV class method deferred, 20-6 
magic static 
DatCommandPtr, 10-11 
manager 
application class, 10-1 
method function 
OLIB long parameters, 1-3 
OLIB prototypes, 1-2 
methods 
ACTIVE class, 11-3 
AIDLE class, 12-2 
ANIMATOR class, 13-4 
APPMAN class, 10-5 
BFILE class, 8-3 
BUZSND class, 13-5 
CLEANUP class, 9-3 
EPFLAT class, 6-8 
EPROOT class deferred, 6-6 
EPROOT class, 6-3 
EPSEG class, 6-10 
FACTIVE class, 14-2 
FCASY class deferred, 14-14 
FCASY class, 14-12 
FCSYNC class, 14-15 
FMAN class deferred, 16-9 
FMAN class, 16-4 
FMFMT class, 16-13 
FMMkK class, 16-12 
FMSCAN class, 16-15 
FMSRC class, 16-17 
FMTARG class, 16-18 
FNODE class deferred, 14-10 
FNODE class, 14-9 
FSCAN class deferred, 14-7 
FSCAN class, 14-5 
IPCS class, 19-3 
LINKCL class, 20-3 
LINKSV class deferred, 20-6 
LINKSV class, 20-5 
LOCS class deferred, 17-3 
LOCS class, 17-3 
PNODE class, 15-4 
PSEL class deferred, 15-11 
PSEL class, 15-7 
PSELVAR class, 15-3 
ROOT class, 2-2 
RSCFILE class, 7-2 


SERFILE class, 8-13 
SERVER class deferred, 19-6 
SERVER class, 19-5 

SGBUF class, 4-2 

SYSTEM class, 18-2 

TIME class, 3-3 

TIMER class, 13-2 
TLVDATA class deferred, 8-10 
TLVDATA class, 8-9 
TLVFILE class, 8-6 

VAFIX class, 5-10 

VAFLAT class, 5-15 
VAROOT class deferred, 5-7 
VAROOT class, 5-4 

VASEG class, 5-17 

VASTER class, 5-12 
VAXVAR class, 5-20 
VAXVARS class, 5-22 


node 


filing systems, 14-8 


OLIB 


class diagrams, 1-3 

class hierarchy, 1-3 

classes overview, 1-1 

classes using, 1-2 

error handling, 1-4 

error numbers panics, 1-5 

library introduction, 1-1 

method function long parameters, 1-3 
method function prototypes, 1-2 
PLIB basis, 1-1 


ACTIVE class HWIM, 11-1 

ACTIVE class methods, 11-3 

active object priorities, 10-2 

active object return value, 10-3 

active object scheduling, 10-3 

active object scheduling mechanism, 10-6 
AIDLE class example, 12-3 

AIDLE class HWIM, 12-1 

AIDLE class idle time computation, 12-3 
AIDLE class methods, 12-2 

AIDLE class pause operation, 12-3 
ANIMATOR class methods, 13-4 
application manager class definition, 10-4 
application manager class diagram, 10-4 
application manager class HWIM, 10-1 
application manager class property, 10-5 
APPMAN class methods, 10-5 

BFILE class, 8-2 

BFILE class methods, 8-3 

bring, 20-1 

BUZSND class methods, 13-5 
CLEANUP class functions convenience, 9-4 
CLEANUP class methods, 9-3 

EPFLAT class, 6-7 

EPFLAT class methods, 6-8 

EPROOT class, 6-2 

EPROOT class deferred methods, 6-6 
EPROOT class methods, 6-3 

EPSEG class, 6-10 

EPSEG class methods, 6-10 

FACTIVE class, 14-1 

FACTIVE class methods, 14-2 


INDEX 


FCASY class, 14-11 

FCASY class deferred methods, 14-14 
FCASY class methods, 14-12 
FCASY sub-class, 14-1 

FCSYNC class, 14-14 

FCSYNC class methods, 14-15 
FCSYNC sub-class, 14-1 

file active object, 14-1 

file lists, 15-1 

file management, 16-1 

file manager example code, 16-19 
file scan local, 17-1 

FMAN class, 16-2 

FMAN class deferred methods, 16-9 
FMAN class methods, 16-4 
FMFMT class, 16-13 

FMFMT class methods, 16-13 
FMFMT sub-class, 16-1 

FMMkK class, 16-12 

FMMkK class methods, 16-12 
FMMkK sub-class, 16-1 

FMSCAN class, 16-14 

FMSCAN class methods, 16-15 
FMSCAN sub-class, 16-1 

FMSRC class, 16-17 

FMSRC class methods, 16-17 
FMSRC sub-class, 16-1 

FMTARG class, 16-18 

FMTARG class methods, 16-18 
FMTARG sub-class, 16-1 

FNODE class, 14-8 

FNODE class deferred methods, 14-10 
FNODE class methods, 14-9 
FNODE sub-class, 14-1 

FSCAN class, 14-3 

FSCAN class deferred methods, 14-7 
FSCAN class methods, 14-5 
FSCAN sub-class, 14-1 
inter-process communications, 19-1 
IPCS, 19-1 

IPCS bring, 20-5 

IPCS class, 19-2 

IPCS class methods, 19-3 

IPCS link paste, 20-5 

link paste, 20-1 

LINKCL class, 20-2 

LINKCL class methods, 20-3 
LINKSV class, 20-4 

LINKSYV class deferred methods, 20-6 
LINKSV class methods, 20-5 
LOCS class deferred methods, 17-3 
LOCS class methods, 17-3 

PNODE class, 15-3 

PNODE class methods, 15-4 

PSEL class, 15-4 

PSEL class deferred methods, 15-11 
PSEL class methods, 15-7 
PSELVAR class, 15-2 

PSELVAR class methods, 15-3 
ROOT class, 2-1 

ROOT class DESTROY method, 2-2 
ROOT class methods, 2-2 
RSCFILE class methods, 7-2 
SCAN class, 17-1 


OLIB REFERENCE 


SERFILE class, 8-11 

SERFILE class methods, 8-13 

SERVER class, 19-4 

SERVER class deferred methods, 19-6 

SERVER class methods, 19-5 

SGBUF class, 4-1 

SGBUF class methods, 4-2 

SYSTEM class, 18-1 

SYSTEM class methods, 18-2 

system services, 18-1 

TIME class, 3-1 

TIME class methods, 3-3 

TIMER active object, 13-1 

TIMER class, 13-1 

TIMER class methods, 13-2 

TLVDATA class, 8-8 

TLVDATA class defered methods, 8-10 

TLVDATA class methods, 8-9 

TLVFILE class, 8-4 

TLVFILE class methods, 8-6 

type-length-value files, 8-4 

VAFIX class, 5-9 

VAFIX class methods, 5-10 

VAFLAT class, 5-14 

VAFLAT class methods, 5-15 

VAROOT class, 5-3 

VAROOT class deferred methods, 5-7 

VAROOT class methods, 5-4 

VASEG class, 5-16 

VASEG class methods, 5-17 

VASTR class, 5-11 

VASTR class methods, 5-12 

VAXVAR class, 5-18 

VAXVAR class methods, 5-20 

VAXVARS class, 5-21 

VAXVARS class methods, 5-22 
panics 

OLIB error numbers, 1-5 
pause operation 

AIDLE example, 12-3 
PLIB 

OLIB relationship to, 1-1 
PNODE class 

AO_ABRUN method, 15-4 

FN_END_LIST method, 15-4 

FN_NODENAME method, 15-4 

methods, 15-4 

oop, 15-3 
PS_ASCEND_PATH 

PSEL class method, 15-9 
PS_DESCEND_PATH 

PSEL class method, 15-9 
PS_DRIVES 

PSEL class method, 15-10 
PS_GET_FILE 

PSEL class method, 15-8 
PS_GETTAG 

PSEL class method, 15-10 
PS_NEW_LIST 

PSEL class method deferred, 15-11 
PS_ORDER 

PSEL class method, 15-10 
PS_SELECT_DIRENTRY 

PSEL class method, 15-9 


viii 


PS_SENSE_FILENAME 
PSEL class method, 15-9 
PS_SET_PATH 
PSEL class method, 15-9 
PS_SETTAG 
PSEL class method, 15-10 
PSEL class 
AO_ABRUN method, 15-7 
AO_CANCEL method, 15-7 
AO_INIT method, 15-7 
FS_DIRNAME method, 15-8 
FS_FILENAME method, 15-8 
FS_FSCAN_END method, 15-8 
methods deferred, 15-11 
methods, 15-7 
oop, 15-4 
PS_ASCEND_PATH method, 15-9 
PS_DESCEND_PATH method, 15-9 
PS_DRIVES method, 15-10 
PS_GET_FILE method, 15-8 
PS_GETTAG method, 15-10 
PS_NEW_LIST deferred method, 15-11 
PS_ORDER method, 15-10 
PS_SELECT_DIRENTRY method, 15-9 
PS_SENSE_FILENAME method, 15-9 
PS_SET_PATH method, 15-9 
PS_SETTAG method, 15-10 
pselvar 
file lists, 15-1 
PSELVAR class 
methods, 15-3 
oop, 15-2 
VA_TEST method, 15-3 
REM 
filing system node, 14-8 
RESOURCE FILES 
class, 7-1 
ROM 
filing system node, 14-8, 17-1 
ROOT class 
DESTROY method, 2-2 
methods, 2-2 
oop superclass, 2-1 
RS_INIT 
RSCFILE class method, 7-2 
RS_READ 
RSCFILE class method, 7-2 
RS_READ_BUF 
RSCFILE class method, 7-2 
RSCFILE class 
DESTROY method, 7-2 
methods, 7-2 
RS_INIT method, 7-2 
RS_READ method, 7-2 
RS_READ_BUF method, 7-2 
SB_ALLOCSEG 
SGBUFEF class method, 4-4 
SB_BACKPOINT 
SGBUF class method, 4-4 
SB_COMPRESS 
SGBUF class method, 4-4 
SB_COUNT 
SGBUF class method, 4-4 


SB_DELETE 

SGBUF class method, 4-3 
SB_EXTRACT 

SGBUF class method, 4-4 
SB_INIT 

SGBUF class method, 4-2 
SB_INSERT 

SGBUF class method, 4-3 
SB_POINT 

SGBUF class method, 4-3 
SCAN class 

file scan local, 17-1 

oop, 17-1 
SERFILE class 

methods, 8-13 

oop class, 8-11 

TD_RESET method, 8-13 

TD_SENSE_ITEM method, 8-14 

TD_SET_FILE method, 8-13 

TD_SET_ITEM method, 8-13 
serial port 

parameter .trm file, 8-11 
SERVER class 

DESTROY method, 19-5 

methods deferredoop, 19-6 

methods, 19-5 

services, 19-4 

SV_ABRUN method, 19-5 

SV_INIT method, 19-5 

SV_RUN deferred method, 19-6 
SGBUF class 

DESTROY method, 4-2 

methods, 4-2 

oop class, 4-1 

SB_ALLOCSEG method, 4-4 

SB_BACKPOINT method, 4-4 

SB_COMPRESS method, 4-4 

SB_COUNT method, 4-4 

SB_DELETE method, 4-3 

SB_EXTRACT method, 4-4 

SB_INIT method, 4-2 

SB_INSERT method, 4-3 

SB_POINT method, 4-3 
sub-class 

FCASY, 14-1 

FCSYNC, 14-1 

FMFMT, 16-1 

FMMK, 16-1 

FMSCAN, 16-1 

FMSRC, 16-1 

FMTARG, 16-1 

FNODE, 14-1 

FSCAN, 14-1 
SV_ABRUN 

SERVER class method, 19-5 
SV_INIT 

LINKSV class method, 20-5 

SERVER class method, 19-5 
SV_RUN 

LINKSV class method, 20-5 

SERVER class method deferred, 19-6 
SY_EXEC_OPEN 

SYSTEM class method, 18-3 


INDEX 


SY_ICON_POS 

SYSTEM class method, 18-2 
SY_INIT 

SYSTEM class method, 18-2 
SY_LINK_PASTE 

SYSTEM class method, 18-3 
SY_LINK_SERVER 

SYSTEM class method, 18-3 
SYSTEM class 

methods, 18-2 

services, 18-1 

SY_EXEC_OPEN method, 18-3 

SY_ICON_POS method, 18-2 

SY_INIT method, 18-2 

SY_LINK_PASTE method, 18-3 

SY_LINK_SERVER method, 18-3 
SYSTEM SERVICES 

class, 18-1 
TD_CHANGED 

TLVDATA class method, 8-9 
TD_LOAD_ITEM 

TLVDATA class method, 8-10 
TD_OPEN 

TLVDATA class method, 8-9 
TD_RESET 

SERFILE class method, 8-13 

TLVDATA class method, 8-10 
TD_SAVE 

TLVDATA class method, 8-9 
TD_SAVE_ITEM 

TLVDATA class method, 8-10 
TD_SENSE_ITEM 

SERFILE class method, 8-14 

TLVDATA class method deferred, 8-10 
TD_SET_FILE 

SERFILE class method, 8-13 

TLVDATA class method deferred, 8-10 
TD_SET_ITEM 

SERFILE class method, 8-13 

TLVDATA class method deferred, 8-10 
TIME class 

methods, 3-3 

oop class, 3-1 

TO_ADD_DAYS method, 3-5 

TO_ADD_MONTHS method, 3-5 

TO_ADD_SECS method, 3-4 

TO_ADD_YEARS method, 3-5 

TO_GET_SYSDAT method, 3-7 

TO_SENSE method, 3-4 

TO_SENSE_FORMAT method, 3-6 

TO_SET method, 3-3 

TO_SET_FORMAT method, 3-6 
TIMER class 

active object, 13-1 

AO_INIT method, 13-2 

AO_QUEUE method, 13-2 

methods, 13-2 

oop, 13-1, 13-2 

TM_QABSOLUTE method, 13-3 
TLVDATA class 

methods deferred, 8-10 

methods, 8-9 

oop class, 8-8 

TD_CHANGED method, 8-9 


OLIB REFERENCE 


TD_LOAD_ITEM method, 8-10 
TD_OPEN method, 8-9 
TD_RESET method, 8-10 
TD_SAVE method, 8-9 
TD_SAVE_ITEM method, 8-10 


TD_SENSE_ITEM method deferred, 8-10 


TD_SET_FILE method deferred, 8-10 

TD_SET_ITEM method deferred, 8-10 
TLVFILE class 

FI_OPEN method, 8-6 

FL_COUNT method, 8-6 

FL_DELREC method, 8-7 

FL_READ_BY_TYPE method, 8-7 

FL_REPLACE method, 8-7 

FL_REWIND method, 8-6 

FL_SENSE_REC method, 8-7 

FL_SET_REC method, 8-6 

FL_WRITE_REC method, 8-6 

methods, 8-6 

oop class, 8-4 
TM_QABSOLUTE 

TIMER class method, 13-3 
TO_ADD_DAYS 

TIME class method, 3-5 
TO_ADD_MONTHS 

TIME class method, 3-5 
TO_ADD_SECS 

TIME class method, 3-4 
TO_ADD_YEARS 

TIME class method, 3-5 
TO_GET_SYSDAT 

TIME class method, 3-7 
TO_SENSE 

TIME class method, 3-4 
TO_SENSE_FORMAT 

TIME class method, 3-6 
TO_SET 

TIME class method, 3-3 
TO_SET_FORMAT 

TIME class method, 3-6 
type-length-value 

files, 8-4 
VA_APPEND 

VAROOT class method, 5-4 
VA_CAPACITY 

VAFLAT class method, 5-15 

VAROOT class method deferred, 5-8 

VASEG class method, 5-17 

VASTR class method, 5-13 
VA_COMPARE 

VAROOT class method, 5-5 
VA_COMPRESS 

VAFLAT class method, 5-15 

VAROOT class method deferred, 5-8 

VASEG class method, 5-17 

VASTR class method, 5-13 
VA_COPY 

VAFIX class method, 5-10 

VAROOT class method deferred, 5-7 

VASTR class method, 5-14 

VAXVAR class method, 5-21 
VA_COUNT 

VAROOT class method, 5-4 


VA_DELETE 

VAROOT class method, 5-5 
VA_DELETEM 

VAFLAT class method, 5-15 

VAROOT class method deferred, 5-8 

VASEG class method, 5-17 

VASTR class method, 5-13 

VAXVAR class method, 5-20 
VA_FINDISQ 

VAROOT class method, 5-6 
VA_INIT 

VAFLAT class method, 5-15 

VAROOT class method deferred, 5-8 

VASEG class method, 5-17 

VASTR class method, 5-12 

VAXVAR class method, 5-20 
VA_INSERT 

VAROOT class method, 5-4 
VA_INSERTISQ 

VAROOT class method, 5-6 
VA_INSERTM 

VAFLAT class method, 5-15 

VAROOT class method deferred, 5-8 

VASEG class method, 5-18 

VASTR class method, 5-13 

VAXVAR class method, 5-20 
VA_KEY 

VAROOT class method, 5-5 
VA_PBUF 

VAFLAT class method, 5-16 

VAROOT class method deferred, 5-9 

VASEG class method, 5-18 

VASTR class method, 5-14 

VAXVAR class method, 5-21 
VA_PREC 

VAFLAT class method, 5-16 

VAROOT class method deferred, 5-9 

VASEG class method, 5-18 

VASTR class method, 5-13 
VA_RECLEN 

VAFIX class method, 5-10 

VAROOT class method deferred, 5-7 

VASTR class method, 5-13 

VAXVAR class method, 5-21 
VA_REPLACE 

VAFIX class method, 5-10 

VAROOT class method, 5-7 

VAXVAR class method, 5-21 
VA_RESET 

VAROOT class method, 5-7 
VA_SEARCH 

VAROOT class method, 5-6 
VA_SORT 

VAROOT class method, 5-6 
VA_SWAP 

VAFIX class method, 5-10 

VAROOT class method deferred, 5-7 
VA_TEST 

PSELVAR class method, 15-3 

VAROOT class method, 5-5 

VAXVAR class method, 5-20 
VAFIX class 

methods, 5-10 

oop class, 5-9 


INDEX 


VA_COPY method, 5-10 VA_PREC method, 5-13 
VA_RECLEN method, 5-10 VA_RECLEN method, 5-13 
VA_REPLACE method, 5-10 VAXVAR class 
VA_SWAP method, 5-10 methods, 5-20 

VAFLAT class oop class, 5-18 
methods, 5-15 VA_COPY method, 5-21 
oop class, 5-14 VA_DELETEM method, 5-20 
VA_CAPACITY method, 5-15 VA_INIT method, 5-20 
VA_COMPRESS method, 5-15 VA_INSERTM method, 5-20 
VA_DELETEM method, 5-15 VA_PBUF method, 5-21 
VA_INIT method, 5-15 VA_RECLEN method, 5-21 
VA_INSERTM method, 5-15 VA_REPLACE method, 5-21 
VA_PBUF method, 5-16 VA_TEST method, 5-20 
VA_PREC method, 5-16 VAXVARS class 

VARIABLE ARRAY methods, 5-22 
classes, 5-1 oop class, 5-21 

VAROOT class 


DESTROY method, 5-4 
methods deferred, 5-7 
methods, 5-4 
oop class, 5-3 
VA_APPEND method, 5-4 
VA_CAPACITY method deferred, 5-8 
VA_COMPARE method, 5-5 
VA_COMPRESS method deferred, 5-8 
VA_COPY method deferred, 5-7 
VA_COUNT method, 5-4 
VA_DELETE method, 5-5 
VA_DELETEM method deferred, 5-8 
VA_FINDISQ method, 5-6 
VA_INIT method deferred, 5-8 
VA_INSERT method, 5-4 
VA_INSERTISQ method, 5-6 
VA_INSERTM method deferred, 5-8 
VA_KEY method, 5-5 
VA_PBUF method deferred, 5-9 
VA_PREC method deferred, 5-9 
VA_RECLEN method deferred, 5-7 
VA_REPLACE method, 5-7 
VA_RESET method, 5-7 
VA_SEARCH method, 5-6 
VA_SORT method, 5-6 
VA_SWAP method deferred, 5-7 
VA_TEST method, 5-5 

VASEG class 
methods, 5-17 
oop class, 5-16 
VA_CAPACITY method, 5-17 
VA_COMPRESS method, 5-17 
VA_DELETEM method, 5-17 
VA_INIT method, 5-17 
VA_INSERTM method, 5-18 
VA_PBUF method, 5-18 
VA_PREC method, 5-18 

VASTR class 
methods, 5-12 
oop class, 5-11 
VA_CAPACITY method, 5-13 
VA_COMPRESS method, 5-13 
VA_COPY method, 5-14 
VA_DELETEM method, 5-13 
VA_INIT method, 5-12 
VA_INSERTM method, 5-13 
VA_PBUF method, 5-14 


